JDBC 前言 在學習了SQL語句後,我們肯定會思考如何使用資料庫里的數據。這個時候,我們便要學習JDBC來將資料庫與JAVA結合在一塊。 正題 什麼是JDBC? Java資料庫連接,(Java Database Connectivity,簡稱JDBC)是Java語言中用來規範客戶端程式如何來訪問數 ...
JDBC
前言
在學習了SQL語句後,我們肯定會思考如何使用資料庫里的數據。這個時候,我們便要學習JDBC來將資料庫與JAVA結合在一塊。
正題
什麼是JDBC?
Java資料庫連接,(Java Database Connectivity,簡稱JDBC)是Java語言中用來規範客戶端程式如何來訪問資料庫的應用程式介面。
JDBC的主要用途
- 與資料庫建立連接
- 發送 SQL 語句
- 處理結果
資料庫驅動
在學習JDBC之前,我們必須瞭解一個東西,驅動。
驅動:兩個設備(兩個應用)之間通信的橋梁。
JDBC的開發步驟
- 載入驅動
- 獲取連接
- 基本操作(CRUD)
- 釋放資源
使用JDBC的準備工作
1.創建一個maven項目(當然你也可以不用這種方法,但maven在開發中最為方便)
【創建方式請看我之前的博客:利用Maven進行導jar包】
2.導入mysql的jar包
<dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> </dependencies>
完成以上的操作,我們便可以開始進行JDBC的學習了。
JDBC的簡單例子(先瞭解一下整體的框架,後面會相應的解釋以及簡化)
package com.jdbc.demo01; import org.junit.Test; import java.sql.*; /** * * JDBC的入門程式 * @author Charles * */ public class JDBCdemo1 {
@Test public void demo01() throws ClassNotFoundException, SQLException { // 1.載入驅動 Class.forName("com.jdbc.Driver"); // 2.獲得連接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root" , "1234"); // 3.基本操作:執行SQL // 3.1獲得執行SQL語句的對象 Statement statement = conn.createStatement(); // 3.2編寫SQL語句: String sql = "select * from user"; // 3.3執行SQL: ResultSet rs = statement.executeQuery(sql); // 3.4遍歷結果集 while (rs.next()){ System.out.println(rs.getInt(("id")+ " ")); System.out.println(rs.getInt(("username")+ " ")); System.out.println(rs.getInt(("password")+ " ")); System.out.println(rs.getInt(("nickname")+ " ")); System.out.println(rs.getInt(("age"))); System.out.println(); } // 4.釋放資源 rs.close(); statement.close(); conn.close(); } }
接下來我來介紹一下上面代碼的含義:
// 1.載入驅動,雙引號裡面的內容一般是標準 Class.forName("com.jdbc.Driver");
此時,你或許會好奇,不是註冊驅動嗎,為什麼代碼是載入驅動。
首先,我們來看看JAVA的API中Driver註冊驅動的介紹
這種方式的確可以完成驅動的註冊,但是實際開發中並不會這麼做。
原因:
如果需要註冊驅動,就會使用DirverManager.registerDriver(new Driver()); ,但是在查詢源代碼的時候,我們發現源代碼中有一段靜態代碼塊已經調用了註冊驅動的方法。因此,如果我們再手動調用註冊,就會導致驅動被註冊兩次。
所以調用 Class.forName 將自動將載入驅動程式類。(具體的原理可以查看一些API文檔)
②:Connection conn = DriverManager.getConnection(url, user, password);
// 2.獲得連接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root", "1234");
參數介紹:
- url:與資料庫連接的路徑
- user:與資料庫連接的用戶名
- password:與資料庫連接的密碼
url:
"jdbc:mysql://localhost:3306/web_test3"
- jdbc:連接資料庫的協議
- mysql:是jdbc的子協議
- localhost:連接的Mysql資料庫伺服器的主機地址【本機:localhost,非本機:連接主機的IP地址】
- 3306:Mysql資料庫伺服器的埠號
- web_test3:資料庫名稱
commit
rollback
接下來我們來看看Statement的詳細操作:
作用:①執行SQL ②執行批處理
①:常用的執行SQL方法: 主要使用的是後兩個
- boolean execute(String sql)
執行查詢,修改,添加,刪除的SQL語句
- ResultSet executeQuery(String sql)
執行查詢(Select 語句)
- int executeUpdate(String sql)
執行修改,添加,刪除的SQL語句
②:常用的執行批處理的方法
addBatch
clearBatch
executeBatch
結果集的獲取可以使用: getxxx(); 通常都會有重載的方法。
getxxx(String columnName);
if(rs != null){ try{ rs.close(); } catch (SQLException e){ e.printStackTrace(); } rs = null; } if(statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if(conn != null){ try{ conn.close(); } catch (SQLException e){ e.printStackTrace(); } conn = null; }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; try{ // 註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 獲得連接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234); // 執行操作 // 創建執行SQL語句對象 statement = conn.createStatement(); // 編寫SQL語句 String sql = "insert into user values (null, 'eee', '123', 'Jack', 21)"; // 執行SQL語句 int num = statement.executeUpdate(sql); if (num > 0){ System.out.println("保存用戶成功!"); } }catch (Exception e){ e.printStackTrace(); }finally { // 釋放資源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; try{ // 註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 獲得連接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234"); // 執行操作 // 創建執行SQL語句對象 statement = conn.createStatement(); // 編寫SQL語句 String sql = "update user set password='2222',nickname='biubiu' where id=6"; // 執行SQL語句 int num = statement.executeUpdate(sql); if (num > 0){ System.out.println("修改用戶成功!"); } }catch (Exception e){ e.printStackTrace(); }finally { // 釋放資源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; try{ // 註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 獲得連接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234"); // 執行操作 // 創建執行SQL語句對象 statement = conn.createStatement(); // 編寫SQL語句 String sql = "delete from user where id=6"; // 執行SQL語句 int num = statement.executeUpdate(sql); if (num > 0){ System.out.println("刪除用戶成功!"); } }catch (Exception e){ e.printStackTrace(); }finally { // 釋放資源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; ResultSet rs = null; try{ // 註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 獲得連接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234"); // 執行操作 // 創建執行SQL語句對象 statement = conn.createStatement(); // 編寫SQL語句 String sql = "select * from user"; // 執行SQL語句 rs = statement.executeQuery(sql); while(rs.next()){ System.out.println(rs.getInt(("id")+ " ")); System.out.println(rs.getInt(("username")+ " ")); System.out.println(rs.getInt(("password")+ " ")); System.out.println(rs.getInt(("nickname")+ " ")); System.out.println(rs.getInt(("age"))); System.out.println(); } }catch (Exception e){ e.printStackTrace(); }finally { // 釋放資源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } if (rs != null){ try { rs.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; ResultSet rs = null; try{ // 註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 獲得連接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234"); // 執行操作 // 創建執行SQL語句對象 statement = conn.createStatement(); // 編寫SQL語句 String sql = "select * from user where id=1"; // 執行SQL語句 rs = statement.executeQuery(sql); if(rs.next()){ System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+re.getString("password")); } }catch (Exception e){ e.printStackTrace(); }finally { // 釋放資源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } if (rs != null){ try { rs.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
目的:包裝成工具類後,能夠更方便地使用JDBC,減少不必要的工作量
package org.charl; import java.sql.*; /** * JDBC工具類 * @author Charles */ public class Demo { // 預設設置 public static final String driverClassName; public static final String url; public static final String username; public static final String password; static { driverClassName = "com.mysql.jdbc.Driver"; url = "jdbc:mysql:///web_test3"; username = "root"; password = "1234"; } // 註冊驅動類 public static void loadDriver(){ try { Class.forName(driverClassName); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 獲得連接 public static Connection getConnection(){ Connection conn = null; try { loadDriver(); conn = DriverManager.getConnection(url,username,password); } catch (SQLException e) { e.printStackTrace(); } return conn; } // 資源釋放 public static void release(Statement st,Connection conn){ if (st != null){ try{ st.close(); } catch (SQLException e){ e.printStackTrace(); } st = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } public static void release(Statement st,Connection conn, ResultSet rs){ if (st != null){ try{ st.close(); } catch (SQLException e){ e.printStackTrace(); } st = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } if (rs != null){ try { rs.close(); }catch (SQLException e){ e.printStackTrace(); } rs = null; } } }
在工具類中解析屬性文件
SQL註入漏洞的解決方法
採用PreparedStatement對象解決SQL註入漏洞問題。該對象將SQL預先進行編譯,使用'?'作為占用符。'?'所代表的內容是SQL所固定。如果再次傳入變數(包括SQL的關鍵字),這個時候也不會識別這些關鍵字。
具體操作:
package com.charles.sql; import java.sql.*; /*** * @return * @author Charles */ public class Demo02 { public boolean login(String username, String password){ Connection conn = null; PreparedStatement preparedStatement = null; ResultSet rs = null; boolean flag = false; try{ conn = org.charl.Demo.getConnection(); String sql = "select * from user where username = ? and password = ?"; preparedStatement = conn.prepareStatement(sql); // 設置參數 preparedStatement.setString(1,username); preparedStatement.setString(2,password); rs = preparedStatement.executeQuery(); if (rs.next()){ flag = true; } } catch (SQLException e){ e.printStackTrace(); } finally { org.charl.Demo.release(preparedStatement,conn,rs); } return flag; } }
接下來展示一下比較完整的實例:
【裡面包含了PreparedStatement等內容,之前的案例看不懂沒關係,這個案例供大家參考】
資料庫web_test4中user表原先的信息
工具類代碼
package org.charl; import java.sql.*; import java.util.Properties; /** * JDBC工具類 * @author Charles */ public class Demo { // 預設設置 public static final String driverClassName; public static final String url; public static final String username; public static final String password; static { driverClassName = "com.mysql.jdbc.Driver"; url = "jdbc:mysql:///web_test4?rewriteBatchedStatements=true?characterEncoding=utf-8"; username = "root"; password = "1234"; } // 註冊驅動類 public static void loadDriver(){ try { Class.forName(driverClassName); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 獲得連接 public static Connection getConnection(){ Connection conn = null; try { loadDriver(); conn = DriverManager.getConnection(url,username,password); } catch (SQLException e) { e.printStackTrace(); } return conn; } // 資源釋放 public static void release(Statement st,Connection conn){ if (st != null){ try{ st.close(); } catch (SQLException e){ e.printStackTrace(); } st = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } public static void release(Statement st,Connection conn, ResultSet rs){ if (st != null){ try{ st.close(); } catch (SQLException e){ e.printStackTrace(); } st = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } if (rs != null){ try { rs.close(); }catch (SQLException e){ e.printStackTrace(); } rs = null; } } }
執行主代碼
package com.charles.sql; import org.junit.Test; import java.sql.*; public class Demo03 { @Test public void Test(){ long begin = System.currentTimeMillis(); Connection conn = null; PreparedStatement preparedStatement = null; ResultSet rs = null; try{ // 註冊驅動 + 獲得連接 conn = org.charl.Demo.getConnection(); // 編寫SQL語句 String sql = "insert into user values(null,?)"; // 預編譯 preparedStatement = conn.prepareStatement(sql); for (int i =1;i<10000;i++){ preparedStatement.setString(1,"name"+i); // 添加到批處理 preparedStatement.addBatch(); // 執行批處理