JDBC基本入門-JDBC中各個介面和類詳解
阿新 • • 發佈:2020-11-21
JDBC:
1. 概念:Java DataBase Connectivity Java 資料庫連線, Java語言操作資料庫 * JDBC本質:其實是官方(sun公司)定義的一套操作所有關係型資料庫的規則,即介面。各個資料庫廠商去實現這套介面,提供資料庫驅動jar包。我們可以使用這套介面(JDBC)程式設計,真正執行的程式碼是驅動jar包中的實現類。 2. 快速入門: * 步驟: 1. 匯入驅動jar包 mysql-connector-java-5.1.37-bin.jar 1.複製mysql-connector-java-5.1.37-bin.jar到專案的libs目錄下 2.右鍵-->Add As Library 2. 註冊驅動 3. 獲取資料庫連線物件 Connection 4. 定義sql 5. 獲取執行sql語句的物件 Statement 6. 執行sql,接受返回結果 7. 處理結果 8. 釋放資源 * 程式碼實現: //1. 匯入驅動jar包 //2.註冊驅動 Class.forName("com.mysql.jdbc.Driver"); //3.獲取資料庫連線物件 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root"); //4.定義sql語句 String sql = "update account set balance = 500 where id = 1"; //5.獲取執行sql的物件 Statement Statement stmt = conn.createStatement(); //6.執行sql int count = stmt.executeUpdate(sql); //7.處理結果 System.out.println(count); //8.釋放資源 stmt.close(); conn.close(); 3. 詳解各個物件: 1. DriverManager:驅動管理物件 * 功能: 1. 註冊驅動:告訴程式該使用哪一個資料庫驅動jar static void registerDriver(Driver driver) :註冊與給定的驅動程式 DriverManager 。 寫程式碼使用: Class.forName("com.mysql.jdbc.Driver"); 通過檢視原始碼發現:在com.mysql.jdbc.Driver類中存在靜態程式碼塊 static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } 注意:mysql5之後的驅動jar包可以省略註冊驅動的步驟。 2. 獲取資料庫連線: * 方法:static Connection getConnection(String url, String user, String password) * 引數: * url:指定連線的路徑 * 語法:jdbc:mysql://ip地址(域名):埠號/資料庫名稱 * 例子:jdbc:mysql://localhost:3306/db3 * 細節:如果連線的是本機mysql伺服器,並且mysql服務預設埠是3306,則url可以簡寫為:jdbc:mysql:///資料庫名稱 * user:使用者名稱 * password:密碼 2. Connection:資料庫連線物件 1. 功能: 1. 獲取執行sql 的物件 * Statement createStatement() * PreparedStatement prepareStatement(String sql) 2. 管理事務: * 開啟事務:setAutoCommit(boolean autoCommit) :呼叫該方法設定引數為false,即開啟事務 * 提交事務:commit() * 回滾事務:rollback() 3. Statement:執行sql的物件 1. 執行sql 1. boolean execute(String sql) :可以執行任意的sql 瞭解 2. int executeUpdate(String sql) :執行DML(insert、update、delete)語句、DDL(create,alter、drop)語句 * 返回值:影響的行數,可以通過這個影響的行數判斷DML語句是否執行成功 返回值>0的則執行成功,反之,則失敗。 3. ResultSet executeQuery(String sql) :執行DQL(select)語句 2. 練習: 1. account表 新增一條記錄 2. account表 修改記錄 3. account表 刪除一條記錄 程式碼: Statement stmt = null; Connection conn = null; try { //1. 註冊驅動 Class.forName("com.mysql.jdbc.Driver"); //2. 定義sql String sql = "insert into account values(null,'王五',3000)"; //3.獲取Connection物件 conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //4.獲取執行sql的物件 Statement stmt = conn.createStatement(); //5.執行sql int count = stmt.executeUpdate(sql);//影響的行數 //6.處理結果 System.out.println(count); if(count > 0){ System.out.println("新增成功!"); }else{ System.out.println("新增失敗!"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { //stmt.close(); //7. 釋放資源 //避免空指標異常 if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } 4. ResultSet:結果集物件,封裝查詢結果 * boolean next(): 遊標向下移動一行,判斷當前行是否是最後一行末尾(是否有資料),如果是,則返回false,如果不是則返回true * getXxx(引數):獲取資料 * Xxx:代表資料型別 如: int getInt() , String getString() * 引數: 1. int:代表列的編號,從1開始 如: getString(1) 2. String:代表列名稱。 如: getDouble("balance") * 注意: * 使用步驟: 1. 遊標向下移動一行 2. 判斷是否有資料 3. 獲取資料 //迴圈判斷遊標是否是最後一行末尾。 while(rs.next()){ //獲取資料 //6.2 獲取資料 int id = rs.getInt(1); String name = rs.getString("name"); double balance = rs.getDouble(3); System.out.println(id + "---" + name + "---" + balance); } * 練習: * 定義一個方法,查詢emp表的資料將其封裝為物件,然後裝載集合,返回。 1. 定義Emp類 2. 定義方法 public List<Emp> findAll(){} 3. 實現方法 select * from emp; 5. PreparedStatement:執行sql的物件 1. SQL注入問題:在拼接sql時,有一些sql的特殊關鍵字參與字串的拼接。會造成安全性問題 1. 輸入使用者隨便,輸入密碼:a' or 'a' = 'a 2. sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 2. 解決sql注入問題:使用PreparedStatement物件來解決 3. 預編譯的SQL:引數使用?作為佔位符 4. 步驟: 1. 匯入驅動jar包 mysql-connector-java-5.1.37-bin.jar 2. 註冊驅動 3. 獲取資料庫連線物件 Connection 4. 定義sql * 注意:sql的引數使用?作為佔位符。 如:select * from user where username = ? and password = ?; 5. 獲取執行sql語句的物件 PreparedStatement Connection.prepareStatement(String sql) 6. 給?賦值: * 方法: setXxx(引數1,引數2) * 引數1:?的位置編號 從1 開始 * 引數2:?的值 7. 執行sql,接受返回結果,不需要傳遞sql語句 8. 處理結果 9. 釋放資源 5. 注意:後期都會使用PreparedStatement來完成增刪改查的所有操作 1. 可以防止SQL注入 2. 效率更高
抽取JDBC工具類 : JDBCUtils
* 目的:簡化書寫 * 分析: 1. 註冊驅動也抽取 2. 抽取一個方法獲取連線物件 * 需求:不想傳遞引數(麻煩),還得保證工具類的通用性。 * 解決:配置檔案 jdbc.properties url= user= password= 3. 抽取一個方法釋放資源 * 程式碼實現: public class JDBCUtils { private static String url; private static String user; private static String password; private static String driver; /** * 檔案的讀取,只需要讀取一次即可拿到這些值。使用靜態程式碼塊 */ static{ //讀取資原始檔,獲取值。 try { //1. 建立Properties集合類。 Properties pro = new Properties(); //獲取src路徑下的檔案的方式--->ClassLoader 類載入器 ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL res = classLoader.getResource("jdbc.properties"); String path = res.getPath(); System.out.println(path);///D:/IdeaProjects/itcast/out/production/day04_jdbc/jdbc.properties //2. 載入檔案 // pro.load(new FileReader("D:\\IdeaProjects\\itcast\\day04_jdbc\\src\\jdbc.properties")); pro.load(new FileReader(path)); //3. 獲取資料,賦值 url = pro.getProperty("url"); user = pro.getProperty("user"); password = pro.getProperty("password"); driver = pro.getProperty("driver"); //4. 註冊驅動 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 獲取連線 * @return 連線物件 */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); } /** * 釋放資源 * @param stmt * @param conn */ public static void close(Statement stmt,Connection conn){ if( stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if( conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 釋放資源 * @param stmt * @param conn */ public static void close(ResultSet rs,Statement stmt, Connection conn){ if( rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if( stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if( conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } * 練習: * 需求: 1. 通過鍵盤錄入使用者名稱和密碼 2. 判斷使用者是否登入成功 * select * from user where username = "" and password = ""; * 如果這個sql有查詢結果,則成功,反之,則失敗 * 步驟: 1. 建立資料庫表 user CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32), PASSWORD VARCHAR(32) ); INSERT INTO USER VALUES(NULL,'zhangsan','123'); INSERT INTO USER VALUES(NULL,'lisi','234'); 2. 程式碼實現: public class JDBCDemo9 { public static void main(String[] args) { //1.鍵盤錄入,接受使用者名稱和密碼 Scanner sc = new Scanner(System.in); System.out.println("請輸入使用者名稱:"); String username = sc.nextLine(); System.out.println("請輸入密碼:"); String password = sc.nextLine(); //2.呼叫方法 boolean flag = new JDBCDemo9().login(username, password); //3.判斷結果,輸出不同語句 if(flag){ //登入成功 System.out.println("登入成功!"); }else{ System.out.println("使用者名稱或密碼錯誤!"); } } /** * 登入方法 */ public boolean login(String username ,String password){ if(username == null || password == null){ return false; } //連線資料庫判斷是否登入成功 Connection conn = null; Statement stmt = null; ResultSet rs = null; //1.獲取連線 try { conn = JDBCUtils.getConnection(); //2.定義sql String sql = "select * from user where username = '"+username+"' and password = '"+password+"' "; //3.獲取執行sql的物件 stmt = conn.createStatement(); //4.執行查詢 rs = stmt.executeQuery(sql); //5.判斷 /* if(rs.next()){//如果有下一行,則返回true return true; }else{ return false; }*/ return rs.next();//如果有下一行,則返回true } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.close(rs,stmt,conn); } return false; } }
JDBC控制事務:
1. 事務:一個包含多個步驟的業務操作。如果這個業務操作被事務管理,則這多個步驟要麼同時成功,要麼同時失敗。 2. 操作: 1. 開啟事務 2. 提交事務 3. 回滾事務 3. 使用Connection物件來管理事務 * 開啟事務:setAutoCommit(boolean autoCommit) :呼叫該方法設定引數為false,即開啟事務 * 在執行sql之前開啟事務 * 提交事務:commit() * 當所有sql都執行完提交事務 * 回滾事務:rollback() * 在catch中回滾事務 4. 程式碼: public class JDBCDemo10 { public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt1 = null; PreparedStatement pstmt2 = null; try { //1.獲取連線 conn = JDBCUtils.getConnection(); //開啟事務 conn.setAutoCommit(false); //2.定義sql //2.1 張三 - 500 String sql1 = "update account set balance = balance - ? where id = ?"; //2.2 李四 + 500 String sql2 = "update account set balance = balance + ? where id = ?"; //3.獲取執行sql物件 pstmt1 = conn.prepareStatement(sql1); pstmt2 = conn.prepareStatement(sql2); //4. 設定引數 pstmt1.setDouble(1,500); pstmt1.setInt(2,1); pstmt2.setDouble(1,500); pstmt2.setInt(2,2); //5.執行sql pstmt1.executeUpdate(); // 手動製造異常 int i = 3/0; pstmt2.executeUpdate(); //提交事務 conn.commit(); } catch (Exception e) { //事務回滾 try { if(conn != null) { conn.rollback(); } } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtils.close(pstmt1,conn); JDBCUtils.close(pstmt2,null); } } }