javaweb:JDBC連線MYSQL資料庫詳解,使用JDBC對資料庫進行CRUD操作以及DAO模式的介紹
JDBC簡介:
JDBC全稱為:Java DataBase Connectivity(java資料庫連線)。
SUN公司為了簡化、統一對資料庫的操作,定義了一套Java操作資料庫的規範,稱之為JDBC。
組成JDBC的2個包:
連結:https://pan.baidu.com/s/1ePw4wDxcsZu9x-3MZHu8FQ
提取碼:0g1z
java.sql
javax.sql
開發JDBC應用需要以上2個包的支援外
還需要匯入相應JDBC的資料庫實現(即資料庫驅動
第一個JDBC程式:
程式設計從user表中讀取資料,並列印在命令列視窗中。
一、搭建實驗環境 :
1、在mysql中建立一個庫,並建立user表和插入表的資料。
2、新建一個Java工程,並匯入資料驅動。
二、編寫程式,在程式中載入資料庫驅動
DriverManager. registerDriver(Driver driver)
三、建立連線(Connection)
Connection conn = DriverManager.getConnection(url,user,pass);
四、建立用於向資料庫傳送SQL的Statement物件,併發送sql
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
五、從代表結果集的ResultSet中取出資料,列印到命令列視窗
六、斷開與資料庫的連線,並釋放相關資源
package cn.itcast.jdbctest; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.junit.Test; /** * JDBC的快速入門 * @author Administrator * */ public class JdbcDemo1 { @Test public void run2(){ Connection conn = null; Statement stmt = null; ResultSet rs = null; try { // 現在這麼做 Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root"); // 編寫SQL語句了 String sql = "select * from t_user"; // 建立能執行SQL語句的Statement物件 stmt = conn.createStatement(); // 執行SQL語句 rs = stmt.executeQuery(sql); // 迴圈變數rs while(rs.next()){ // 拿出來 int id = rs.getInt("id"); String username = rs.getString("username"); String password = rs.getString("password"); System.out.println(id+" "+username+" "+password); } } catch (Exception e) { e.printStackTrace(); }finally{ if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } rs = null; } if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } stmt = null; } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn = null; } } } @Test public void run1() throws SQLException, ClassNotFoundException{ /** * 1.完成驅動的註冊 * 2.獲取連結 * 3.執行SQL語句 * 4.釋放資源 */ // 註冊驅動 // DriverManager.registerDriver(new Driver()); // 現在這麼做 Class.forName("com.mysql.jdbc.Driver"); // 獲取連結 // Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day17", "root", "root"); Connection conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root"); // 編寫SQL語句了 String sql = "select * from t_user"; // 建立能執行SQL語句的Statement物件 Statement stmt = conn.createStatement(); // 執行SQL語句 ResultSet rs = stmt.executeQuery(sql); // 迴圈變數rs while(rs.next()){ // 拿出來 int id = rs.getInt("id"); String username = rs.getString("username"); String password = rs.getString("password"); System.out.println(id+" "+username+" "+password); } rs.close(); stmt.close(); conn.close(); } }
JDBC程式設計步驟:
裝載驅動程式
建立連線
操作資料
釋放資源
程式詳解—DriverManager:
DriverManager類的是管理一組 JDBC 驅動程式的基本服務。作用有兩個,如下:
註冊驅動
•static void registerDriver(Driver driver)方法進行註冊驅動
•但是這種方式不是很好,原因如下:
•讓應用程式依賴具體的驅動包,如果是切換資料庫還需要修改原始碼才能完成。
•呼叫該方法導致驅動被註冊兩次,通過檢視驅動的原始碼能發現次問題。
•所以在實際開發中不會這麼做?具體做法如下:
•Class.forName("com.mysql.jdbc.Driver");
獲取連結物件
資料庫URL:
URL用於標識資料庫的位置,程式設計師通過URL地址告訴JDBC程式連線哪個資料庫,URL的寫法為:
jdbc: mysql: // localhost:3306/test ? key=value
l常用資料庫URL地址的寫法:
•Oracle寫法:jdbc:oracle:thin:@localhost:1521:sid
•MySql—jdbc:mysql://localhost:3306/sid
Mysql的url地址的簡寫形式: jdbc:mysql:///sid
常用屬性:useUnicode=true&characterEncoding=UTF-8
程式詳解—Connection:
Jdbc程式中的Connection,它用於代表資料庫的連結,Collection是資料庫程式設計中最重要的一個物件,客戶端與資料庫所有互動都是通過connection物件完成的,
有兩個作用:
•建立執行SQL語句的物件:
•createStatement():建立向資料庫傳送sql的statement物件
•prepareStatement(sql) :建立向資料庫傳送預編譯sql的PreparedSatement物件
•prepareCall(sql):建立執行儲存過程的CallableStatement物件。
• 管理事物:
•setAutoCommit(boolean autoCommit):設定事務是否自動提交。
•commit() :在連結上提交事務。 ---與事務相關!!
•rollback() :在此連結上回滾事務。
程式詳解—Statement -- 一次操作:
Jdbc程式中的Statement物件用於向資料庫傳送SQL語句, Statement物件常用方法:
•執行SQL語句
•executeQuery(String sql) :用於向資料傳送查詢語句。
•executeUpdate(String sql):用於向資料庫傳送insert、update或delete語句
•execute(String sql):用於向資料庫傳送任意sql語句
•執行批處理
•addBatch(String sql) :把多條sql語句放到一個批處理中。
•executeBatch():向資料庫傳送一批sql語句執行。
程式詳解—ResultSet:
Jdbc程式中的ResultSet用於代表Sql語句的執行結果。Resultset封裝執行結果時,採用的類似於表格的方式。ResultSet 物件維護了一個指向表格資料行的遊標cursor,初始的時候,遊標在第一行之前,呼叫ResultSet.next() 方法,可以使遊標指向具體的資料行,進而呼叫方法獲取該行的資料。
ResultSet既然用於封裝執行結果的,所以該物件提供的大部分方法都是用於獲取資料的get方法:
•獲取任意型別的資料
•getObject(int index)
•getObject(string columnName)
•獲取指定型別的資料,例如:
•getString(int index)
•getString(String columnName)
常用資料型別轉換表:
遍歷查詢結果:
程式詳解—釋放資源:
Jdbc程式執行完後,切記要釋放程式在執行過程中,建立的那些與資料庫進行互動的物件,這些物件通常是ResultSet, Statement和Connection物件。
特別是Connection物件,它是非常稀有的資源,用完後必須馬上釋放,如果Connection不能及時、正確的關閉,極易導致系統宕機。Connection的使用原則是儘量晚建立,儘量早的釋放。
為確保資源釋放程式碼能執行,資源釋放程式碼也一定要放在finally語句中。
使用JDBC對資料庫進行CRUD:
Jdbc中的statement物件用於向資料庫傳送SQL語句,想完成對資料庫的增刪改查,只需要通過這個物件向資料庫傳送增刪改查語句即可。
Statement物件的executeUpdate方法,用於向資料庫傳送增、刪、改的sql語句,executeUpdate執行完後,將會返回一個整數(即增刪改語句導致了資料庫幾行資料發生了變化)。
Statement.executeQuery方法用於向資料庫傳送查詢語句,executeQuery方法返回代表查詢結果的ResultSet物件。
CRUD操作-create:
使用executeUpdate(String sql)方法完成資料新增操作,示例操作:
Statement st = conn.createStatement();
String sql = "insert into user(….) values(…..) ";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("插入成功!!!");
}
CRUD操作-updata:
使用executeUpdate(String sql)方法完成資料修改操作,示例操作:
Statement st = conn.createStatement();
String sql = “update user set name=‘’ where name=‘’";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println(“修改成功!!!");
}
CRUD操作-delete:
使用executeUpdate(String sql)方法完成資料刪除操作,示例操作:
Statement st = conn.createStatement();
String sql = “delete from user where id=1;
int num = st.executeUpdate(sql);
if(num>0){
System.out.println(“刪除成功!!!");
}
CRUD操作-Retrieve/Read:
使用executeQuery(String sql)方法完成資料查詢操作,示例操作:
Statement st = conn.createStatement();
String sql = “select * from user where id=1;
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
//根據獲取列的資料型別,分別呼叫rs的相應方法
//對映到java物件中
}
增刪改查例項:
package cn.itcast.jdbctest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import cn.itcast.utils.MyJdbcUtil;
/**
* 完成t_user表的增刪改查
* @author Administrator
*
*/
public class JdbcDemo3 {
@Test
public void testSelect(){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 載入驅動,現在不用了,直接獲取連結物件
// MyJdbcUtil封裝工具類,下文有詳細解析,在裡面封裝了固定的模組,簡化程式碼
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "select * from t_user";
// 建立執行
stmt = conn.createStatement();
// 執行
rs = stmt.executeQuery(sql);
// 迴圈遍歷
while(rs.next()){
System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(rs, stmt, conn);
}
}
/**
* 測試新增的功能
*/
@Test
public void testInsert(){
Connection conn = null;
Statement stmt = null;
try {
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲取連結
conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
// 編寫SQL語句
String sql = "insert into t_user values (null,'小鳳','111')";
// 能執行該SQL語句的物件
stmt = conn.createStatement();
// 執行
int index = stmt.executeUpdate(sql);
if(index > 0){
System.out.println("新增資料成功");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
/**
* 測試修改的功能
*/
@Test
public void testUpdate(){
Connection conn = null;
Statement stmt = null;
try {
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲取連結
conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
// 編寫SQL語句
String sql = "update t_user set username = '如花',password='555' where id = 5 ";
// 能執行該SQL語句的物件
stmt = conn.createStatement();
// 執行
int index = stmt.executeUpdate(sql);
if(index > 0){
System.out.println("修改資料成功");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
/**
* 測試刪除的功能
*/
@Test
public void testDelete(){
Connection conn = null;
Statement stmt = null;
try {
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲取連結
conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
// 編寫SQL語句
String sql = "delete from t_user where id = 5";
// 能執行該SQL語句的物件
stmt = conn.createStatement();
// 執行
int index = stmt.executeUpdate(sql);
if(index > 0){
System.out.println("刪除資料成功");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
}
JDBC工具類的封裝和CURD:
使用JDBC完成資料的CURD操作具有很多重複性的程式碼,像驅動載入、獲取連結、釋放資源等,所以可以封裝成工具類方便使用。
封裝工具類:
package cn.itcast.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 操作JDBC
* @author Administrator
*/
public class MyJdbcUtil {
public static final String DRIVERCLASS;
public static final String URL;
public static final String USERNAME;
public static final String PASSWORD;
// 想給常量賦值
static{
// 解析db.properties檔案
// Properties工具類,載入檔案
Properties pro = new Properties();
// 獲取輸入流
InputStream in = MyJdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
try {
pro.load(in);
} catch (IOException e) {
e.printStackTrace();
}
// 通過Properties獲取內容
DRIVERCLASS = pro.getProperty("driverClass");
URL = pro.getProperty("url");
USERNAME = pro.getProperty("username");
PASSWORD = pro.getProperty("password");
}
/**
* 載入驅動
*/
public static void loadDriver(){
try {
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 獲取連結
* @return
*/
public static Connection getConnection(){
// 載入驅動
loadDriver();
// 獲取連結物件
try {
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 釋放資源
* @param rs
* @param stmt
* @param conn
*/
public static void release(ResultSet rs,Statement stmt,Connection conn){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
/**
* 釋放資源的方法
* @param stmt
* @param conn
*/
public static void release(Statement stmt,Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
db.properties配置資料庫檔案(這個檔案是在src的根目錄下建立的):
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///day17
username=root
password=root
JavaEE模式-DAO 模式:
SUN公司在早期的JAVAEE體系分成了三層經典結構:WEB層 (Servlet/JSP)– 業務層(JavaBean) – 持久層(JDBC)
早期採用Servlet+JSP+JavaBean+JDBC架構完成開發
現在採用框架來完成開發(ssh框架)Struts2 + Spring + Hibernate
DAO模式就是持久層的一種解決方案,封裝對於資料來源及其資料的單個操作,需要提供一組介面,供業務層訪問,業務呼叫DAO的程式碼時候需要傳遞一個物件。
資料來源可能是檔案、資料庫等任意儲存方式
負責管理與資料來源的連線
負責資料的存取(CRUD)
DAO模式的類圖:
DAO 模式中的物件:
Business Object
•代表資料的使用者
DataAccessObject
•抽象並封裝了對底層資料來源的操作
DataSource
•資料來源
TransferObject
•表示資料的Java Bean
例項(java三層架構模式)—使用者登陸:
原始碼已上傳到github:https://github.com/LazyTraveller/standard-login
1.搭建環境
2.匯入jar包(MySQL驅動包,JSTL包)
架構:
LoginServlet.java:
package cn.itcast.action;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import cn.itcast.service.UserService;
import cn.itcast.vo.User;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = -5933952794357976456L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 接收資料
* 封裝資料
* 處理資料
* 顯示結果
*/
// 設定編碼
request.setCharacterEncoding("UTF-8");
// 接收資料
Map<String, String []> map = request.getParameterMap();
User user = new User();
try {
// 封裝資料
BeanUtils.populate(user, map);
// 呼叫業務層的程式碼
UserService us = new UserService();
// 判斷是否登陸
User existUser = us.loginUser(user);
// 判斷是否為null
if(existUser == null){
// 說明失敗
// 向域中存值
request.setAttribute("msg", "使用者名稱或者密碼錯誤");
// 使用轉發
request.getRequestDispatcher("/pages/login.jsp").forward(request, response);
}else{
// 把使用者的資訊儲存到session中
request.getSession().setAttribute("existUser", existUser);
// 重定向到頁面
response.sendRedirect(request.getContextPath()+"/pages/success.jsp");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
UserDao.java: 這是一個介面
package cn.itcast.dao;
import java.util.List;
import cn.itcast.vo.User;
public interface UserDao {
public User findUser(User user);
public User findUserByPrepared(User user);
// 新增資料
public void insert(User user);
// 修改資料
public void update(User user);
// 刪除資料
public void delete(User user);
// 通過主鍵來查詢單個使用者
public User findUserById(int id);
// 查詢所有使用者
public List<User> findUsers();
}
防止SQL注入漏洞:
1.前臺校驗
2.後臺校驗(prepareStatement)
UserDaolmple.java: 這是UserDao的實現類
package cn.itcast.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import cn.itcast.utils.MyJdbcUtil;
import cn.itcast.vo.User;
public class UserDaoImple implements UserDao {
/**
* 防止SQL注入
*/
public User findUserByPrepared(User user) {
// 完成登陸的功能(通過使用者名稱和密碼查詢資料庫)
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 先獲取連結物件
conn = MyJdbcUtil.getConnection();
// 編寫的SQL語句不同
String sql = "select * from t_user where username = ? and password = ? ";
// 預編譯(已經把SQL傳送給伺服器進行預編譯,格式就固定了)
stmt = conn.prepareStatement(sql);
// 設定引數的值
stmt.setString(1, user.getUsername()); // bbb ' or ' 1 = 1不認識or關鍵字
stmt.setString(2, user.getPassword());
// 執行SQL(不帶SQL語句的)
rs = stmt.executeQuery();
// 如果有
if(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 完成登陸的操作
*/
public User findUser(User user) {
// 完成登陸的功能(通過使用者名稱和密碼查詢資料庫)
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 先獲取連結物件
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "select * from t_user where username = '"+user.getUsername()+"' and password= '"+user.getPassword()+"' ";
// 執行SQL
stmt = conn.createStatement();
// 執行SQL語句,如果有會查詢出一條記錄
rs = stmt.executeQuery(sql);
// 如果有
if(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 完成新增的功能
*/
public void insert(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "insert into t_user values (null,?,?)";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 設定引數
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
// 執行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 修改使用者的資料
*/
public void update(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "update t_user set username = ? , password = ? where id = ?";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 設定引數
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
stmt.setInt(3, user.getId());
// 執行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 刪除使用者的記錄
*/
public void delete(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "delete from t_user where id = ?";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 設定引數
stmt.setInt(1, user.getId());
// 執行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 通過使用者的主鍵來獲取使用者的詳細資訊
*/
public User findUserById(int id) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "select * from t_user where id = ?";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 設定引數
stmt.setInt(1, id);
// 執行SQL
rs = stmt.executeQuery();
// 一條記錄
if(rs.next()){
User u = new User();
u.setId(id);
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 獲取所有的使用者資訊
*/
public List<User> findUsers() {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
List<User> list = new ArrayList<User>();
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "select * from t_user";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 執行SQL
rs = stmt.executeQuery();
// 一條記錄
while(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
list.add(u);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
@Test
public void run(){
User u = new User(6,"eee","333");
// insert(u);
// update(u);
// delete(u);
//User u2 = findUserById(2);
//System.out.println(u2);
List<User> list = findUsers();
for (User user : list) {
System.out.println(user);
}
}
}
package cn.itcast.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import cn.itcast.utils.MyJdbcUtil;
import cn.itcast.vo.User;
public class UserDaoImple implements UserDao {
/**
* 防止SQL注入
*/
public User findUserByPrepared(User user) {
// 完成登陸的功能(通過使用者名稱和密碼查詢資料庫)
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 先獲取連結物件
conn = MyJdbcUtil.getConnection();
// 編寫的SQL語句不同
String sql = "select * from t_user where username = ? and password = ? ";
// 預編譯(已經把SQL傳送給伺服器進行預編譯,格式就固定了)
stmt = conn.prepareStatement(sql);
// 設定引數的值
stmt.setString(1, user.getUsername()); // bbb ' or ' 1 = 1不認識or關鍵字
stmt.setString(2, user.getPassword());
// 執行SQL(不帶SQL語句的)
rs = stmt.executeQuery();
// 如果有
if(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 完成登陸的操作
*/
public User findUser(User user) {
// 完成登陸的功能(通過使用者名稱和密碼查詢資料庫)
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 先獲取連結物件
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "select * from t_user where username = '"+user.getUsername()+"' and password= '"+user.getPassword()+"' ";
// 執行SQL
stmt = conn.createStatement();
// 執行SQL語句,如果有會查詢出一條記錄
rs = stmt.executeQuery(sql);
// 如果有
if(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 完成新增的功能
*/
public void insert(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "insert into t_user values (null,?,?)";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 設定引數
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
// 執行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 修改使用者的資料
*/
public void update(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "update t_user set username = ? , password = ? where id = ?";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 設定引數
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
stmt.setInt(3, user.getId());
// 執行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 刪除使用者的記錄
*/
public void delete(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "delete from t_user where id = ?";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 設定引數
stmt.setInt(1, user.getId());
// 執行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 通過使用者的主鍵來獲取使用者的詳細資訊
*/
public User findUserById(int id) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "select * from t_user where id = ?";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 設定引數
stmt.setInt(1, id);
// 執行SQL
rs = stmt.executeQuery();
// 一條記錄
if(rs.next()){
User u = new User();
u.setId(id);
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 獲取所有的使用者資訊
*/
public List<User> findUsers() {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
List<User> list = new ArrayList<User>();
try {
// 獲取連結
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句
String sql = "select * from t_user";
// 預編譯SQL
stmt = conn.prepareStatement(sql);
// 執行SQL
rs = stmt.executeQuery();
// 一條記錄
while(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
list.add(u);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}finally{
// 釋放資源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
@Test
public void run(){
User u = new User(6,"eee","333");
// insert(u);
// update(u);
// delete(u);
//User u2 = findUserById(2);
//System.out.println(u2);
List<User> list = findUsers();
for (User user : list) {
System.out.println(user);
}
}
}
UserService.java:
package cn.itcast.service;
import cn.itcast.dao.UserDao;
import cn.itcast.dao.UserDaoImple;
import cn.itcast.vo.User;
/**
* 使用者相關的業務類
* @author Administrator
*
*/
public class UserService {
/**
* 使用者是否可以登陸
* @param user
* @return
*/
public User loginUser(User user){
UserDao dao = new UserDaoImple();
// 防止SQL注入
return dao.findUserByPrepared(user);
}
}
MyjdbcUtil.java:
package cn.itcast.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 操作JDBC
* @author Administrator
*/
public class MyJdbcUtil {
public static final String DRIVERCLASS;
public static final String URL;
public static final String USERNAME;
public static final String PASSWORD;
// 想給常量賦值
static{
// 解析db.properties檔案
// Properties工具類,載入檔案
Properties pro = new Properties();
// 獲取輸入流
InputStream in = MyJdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
try {
pro.load(in);
} catch (IOException e) {
e.printStackTrace();
}
// 通過Properties獲取內容
DRIVERCLASS = pro.getProperty("driverClass");
URL = pro.getProperty("url");
USERNAME = pro.getProperty("username");
PASSWORD = pro.getProperty("password");
}
/**
* 載入驅動
*/
public static void loadDriver(){
try {
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 獲取連結
* @return
*/
public static Connection getConnection(){
// 載入驅動
loadDriver();
// 獲取連結物件
try {
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 釋放資源
* @param rs
* @param stmt
* @param conn
*/
public static void release(ResultSet rs,Statement stmt,Connection conn){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
/**
* 釋放資源的方法
* @param stmt
* @param conn
*/
public static void release(Statement stmt,Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
User.java:
package cn.itcast.vo;
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(int id, String username, String password) {
super();
this.id = id;
this.username = username;
this.password = password;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password="
+ password + "]";
}
}
login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>使用者登陸</h3>
<font color="red">${ msg }</font>
<form action="${ pageContext.request.contextPath }/login" method="post">
使用者名稱:<input type="text" name="username" /><br/>
密碼:<input type="password" name="password" /><br/>
<input type="submit" value="登陸">
</form>
</body>
</html>
success.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>歡迎頁面</h3>
<c:if test="${ empty existUser }">
<h3>親,您還沒有登陸,請您<a href="${ pageContext.request.contextPath }/pages/login.jsp">登陸</a></h3>
</c:if>
<c:if test="${ not empty existUser }">
<h3>親,歡迎您:${ existUser.username }</h3>
</c:if>
</body>
</html>
使用JDBC處理大資料:
在實際開發中,程式需要把大文字 Text 或二進位制資料 Blob儲存到資料庫。
Text是mysql叫法,Oracle中叫Clob
基本概念:大資料也稱之為LOB(Large Objects),LOB又分為:
•clob和blob
•clob用於儲存大文字。Text
•blob用於儲存二進位制資料,例如影象、聲音、二進位制文等。
對MySQL而言只有blob,而沒有clob,mysql儲存大文字採用的是Text,Text和blob分別又分為:
•TINYTEXT(255)、TEXT(64k)、MEDIUMTEXT(16M)和LONGTEXT(4G)
•TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB
使用JDBC處理大文字:
l對於MySQL中的Text型別,可呼叫如下方法設定:
PreparedStatement.setCharacterStream(index, reader, length);
//注意length長度須設定,並且設定為int型
//當包過大時修改配置:[mysqld] max_allowed_packet=64M
l對MySQL中的Text型別,可呼叫如下方法獲取:
reader = resultSet. getCharacterStream(i);
等價於
reader = resultSet.getClob(i).getCharacterStream();
使用JDBC處理二進位制資料:
對於MySQL中的BLOB型別,可呼叫如下方法設定:
PreparedStatement. setBinaryStream(i, inputStream, length);
對MySQL中的BLOB型別,可呼叫如下方法獲取:
InputStream in = resultSet.getBinaryStream(i);
InputStream in = resultSet.getBlob(i).getBinaryStream();
使用JDBC進行批處理:
業務場景:當需要向資料庫傳送一批SQL語句執行時,應避免向資料庫一條條的傳送執行,而應採用JDBC的批處理機制,以提升執行效率。
實現批處理有兩種方式,第一種方式:
•Statement.addBatch(sql)
•執行批處理SQL語句
•executeBatch()方法:執行批處理命令
•clearBatch()方法:清除批處理命令
使用JDBC進行批處理:
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConnection();
String sql1 = "insert into person(name,password,email,birthday)
values('kkk','123','[email protected]','1978-08-08')";
String sql2 = "update user set password='123456' where id=3";
st = conn.createStatement();
st.addBatch(sql1); //把SQL語句加入到批命令中
st.addBatch(sql2); //把SQL語句加入到批命令中
st.executeBatch();
} finally{
JdbcUtil.free(conn, st, rs);
}
採用Statement.addBatch(sql)方式實現批處理:
優點:可以向資料庫傳送多條不同的SQL語句。
缺點:
SQL語句沒有預編譯。
當向資料庫傳送多條語句相同,但僅引數不同的SQL語句時,需重複寫上很多條SQL語句。例如:
Insert into user(name,password) values(‘aa’,’111’);
Insert into user(name,password) values(‘bb’,’222’);
Insert into user(name,password) values(‘cc’,’333’);
Insert into user(name,password) values(‘dd’,’444’);
實現批處理的第二種方式:
•PreparedStatement.addBatch()
conn = JdbcUtil.getConnection();
String sql = "insert into person(name,password,email,birthday) values(?,?,?,?)";
st = conn.prepareStatement(sql);
for(int i=0;i<50000;i++){
st.setString(1, "aaa" + i);
st.setString(2, "123" + i);
st.setString(3, "aaa" + i + "@sina.com");
st.setDate(4,new Date(1980, 10, 10));
st.addBatch();
if(i%1000==0){
st.executeBatch();
st.clearBatch();
}
}
st.executeBatch();
採用PreparedStatement.addBatch()實現批處理
•優點:傳送的是預編譯後的SQL語句,執行效率高。
•缺點:只能應用在SQL語句相同,但引數不同的批處理中。因此此種形式的批處理經常用於在同一個表中批量插入資料,或批量更新表的資料。