JDBC的簡單介紹 概念 JDBC : Java Database Connectivity,java連接資料庫,使用Java操作資料庫的技術。 本質 : 其實就是sun公司定義的一套操作所有關係型資料庫的規則,即介面。 各個資料庫廠商去實現這套介面,提供資料庫操作 驅動jar包 ,我們可以使用這套 ...
JDBC的簡單介紹
概念
- JDBC : Java Database Connectivity,java連接資料庫,使用Java操作資料庫的技術。
- 本質 : 其實就是sun公司定義的一套操作所有關係型資料庫的規則,即介面。
各個資料庫廠商去實現這套介面,提供資料庫操作驅動jar包,我們可以使用這套
介面進行(JDBC)編程,真正執行的代碼是驅動jar包的實現類。
快速入門
本人使用的是jdk10和mysql-connector-java-5.1.45-bin.jar。
步驟:
- 導入驅動jar包
- 項目根目錄創建文件夾libs。
- 將mysql-connector-java-5.1.45-bin.jar複製到libs目錄下
- 右擊libs下,Add as Library將jar包導入項目中
- 註冊驅動
- 獲取資料庫連接對象(Collection)
- 定義sql
- 獲取執行sql語句的對象 Statement
- 執行sql,接受返回結果(ResultSet)
- 處理結果
釋放資源
// 2. 註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 3. 獲取連接對象Collection Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "nrblwbb7"); // 4. 定義sql String sql = "UPDATE STUDENT SET AGE = 23 WHERE NAME = '王智'"; // 5. 獲取執行sql語句的對象 Statement Statement statement = conn.createStatement(); // 6. 執行sql,接受返回結果(ResultSet) int result = statement.executeUpdate(sql); // 7. 處理結果 System.out.println(result); // 8. 釋放資源 statement.close(); conn.close();
詳解各個對象
- DriverManager:驅動管理對象
- Connection:資料庫連接對象
- Statement:執行sql對象
- ResultSet:結果集對象
- PreparedStatement :執行sql對象
DriverManager
功能:
- 註冊驅動:告訴程式該使用哪一個資料庫驅動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包可以省略註冊驅動的步驟。
- 獲取資料庫連接
- 方法:static Connection getConnection(String url, String user, String password)
- 參數:
- url:指定連接的路徑
- 語法:jdbc:mysql://ip地址(功能變數名稱):埠號/資料庫名稱
- 例子:jdbc:mysql://localhost:3306/db
- 細節:如果連接的是本機mysql伺服器,並且mysql服務預設埠是3306,則url可以簡寫為:jdbc:mysql:///資料庫名稱
- jdbc是連接資料庫的協議,mysql是連接mysql資料庫的子協議
- user:用戶名
- password:密碼
- url:指定連接的路徑
Collection連接對象
功能:
- 獲取執行sql的對象
- Statement createStatement()
- PreparedStatement prepareStatement(String sql)
- 管理事務
- 開啟事務:setAutoCommit(boolean autoCommit) :調用該方法設置參數為false,即開啟事務
- 提交事務:commit()
- 回滾事務:rollback()
Statement執行靜態sql對象
功能:
- 執行sql
- boolean execute(String sql) :可以執行任意的sql (瞭解)
- int executeUpdate(String sql) :執行DML(insert、update、delete)語句、DDL(create,alter、drop)語句
- 返回值:影響的行數,可以通過這個影響的行數判斷DML語句是否執行成功 返回值>0的則執行成功,反之,則失敗。
- ResultSet executeQuery(String sql) :執行DQL(select)語句
插入舉例:
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 1. 載入驅動
Class.forName("com.mysql.jdbc.Driver");
// 2. 獲取連接對象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?useSSL=true", "root", "nrblwbb7");
// 3. 創建sql
String sql = "INSERT INTO ACCOUNT VALUES (NULL,'網址',2000)";
// 4. 獲取執行sql對象
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 {
// 7. 釋放資源
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
修改舉例:
public static void main(String[] args) {
/**
* 由於Connection和Statement實現了AutoCloseable介面,所以可以使用自動關閉
*/
try(
// 2.獲取Connection對象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3?useSSL=true",
"root",
"nrblwbb7") ;
// 3. 獲取Statement對象
Statement stmt = conn.createStatement()
){
// 1.載入驅動
Class.forName("com.mysql.jdbc.Driver");
// 4. 創建sql
String sql = "UPDATE ACCOUNT SET BALANCE = 1500 WHERE NAME = '網址'";
// 5. 執行sql
int count = stmt.executeUpdate(sql);
// 6. 處理結果
System.out.println(count);
if(count > 0){
System.out.println("修改成功");
}else{
System.out.println("操作失敗或者記錄未更改");
}
// 7. 關閉連接,由於try..with..resource會自動關閉,所以無須擔心
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
刪除舉例:
public static void main(String[] args) {
/**
* 由於Connection和Statement實現了AutoCloseable介面,所以可以使用自動關閉
*/
try(
// 2.獲取Connection對象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3?useSSL=true",
"root",
"nrblwbb7") ;
// 3. 獲取Statement對象
Statement stmt = conn.createStatement()
){
// 1.載入驅動
Class.forName("com.mysql.jdbc.Driver");
// 4. 創建sql
String sql = "DELETE FROM ACCOUNT WHERE NAME = '網址'";
// 5. 執行sql
int count = stmt.executeUpdate(sql);
// 6. 處理結果
System.out.println(count);
if(count > 0){
System.out.println("刪除成功");
}else{
System.out.println("刪除失敗");
}
// 7. 關閉連接,由於try..with..resource會自動關閉,所以無須擔心
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
ResultSet:結果及對象,封裝查詢結果
功能:
- 封裝查詢結果:
- boolean next(): 游標向下移動一行,判斷當前行是否是最後一行末尾(是否有數據),如果是,則返回false,如果不是則返回true
- getXxx(參數):獲取數據
- Xxx:代表數據類型 如: int getInt() , String getString()
- 參數:
- int:代表列的編號,從1開始 如: getString(1)
- String:代表列名稱。 如: getDouble("balance")
- 註意:
- 使用步驟:
- 游標向下移動一行
- 判斷是否有數據
- 獲取數據
- 使用步驟:
舉個簡單例子:
@Test
public void selectDemo(){
try {
// 1.載入驅動
Class.forName("com.mysql.jdbc.Driver");
// 2.創建sql語句
String sql = "select * from account";
try(
// 3.獲取連接對象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3?useSSL=true",
"root",
"root");
// 4.獲取執行sql語句對象
Statement stmt = conn.createStatement()
){
// 5.執行sql
ResultSet rs = stmt.executeQuery(sql);
// 6.處理結果集
while(rs.next()){
// 獲取id
int id = rs.getInt("id");
// 獲取姓名
String name = rs.getString("name");
// 獲取賬戶餘額
double balance = rs.getDouble("balance");
// 正確的處理應該是封裝為對象,進行處理,這就簡單展示下
System.out.println("id = " + id + ", name = " + name + ", balance = " + balance);
}
} catch (SQLException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
PreparedStatement:執行動態sql的對象
功能:
- 執行動態的sql
- SQL註入問題:在拼接sql時,有一些sql的特殊關鍵字參與字元串的拼接。會造成安全性問題
- 輸入用戶隨便,輸入密碼:a' or 'a' = 'a
- sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'
- 解決sql註入問題:使用PreparedStatement對象來解決
- 預編譯的SQL:參數使用?作為占位符
- 步驟:
- 導入驅動jar包 mysql-connector-java-5.1.45-bin.jar
- 註冊驅動
- 獲取資料庫連接對象 Connection
- 定義sql
- 註意:sql的參數使用?作為占位符。 如:select * from user where username = ? and password = ?;
- 獲取執行sql語句的對象 PreparedStatement Connection.prepareStatement(String sql)
- 給?賦值:
- 方法: setXxx(參數1,參數2)
- 參數1:?的位置編號 從1 開始
- 參數2:?的值
- 方法: setXxx(參數1,參數2)
- 執行sql,接受返回結果,不需要傳遞sql語句
- 處理結果
- 釋放資源
- 註意:後期都會使用PreparedStatement來完成增刪改查的所有操作
- 可以防止SQL註入
- 效率更高
- SQL註入問題:在拼接sql時,有一些sql的特殊關鍵字參與字元串的拼接。會造成安全性問題
封裝工具類
src下db.properties的信息:
# 驅動
driver=com.mysql.jdbc.Driver
# url
url=jdbc:mysql://127.0.0.1:3306/db3?useSSL=true
# 用戶
username=root
# 密碼
password=root
封裝的工具類如下:
public class JDBCUtils {
private static String driver;
private static String url;
private static String username;
private static String password;
static{
try {
// 讀取配置文件
InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties pro = new Properties();
pro.load(inputStream);
// 靜態變數賦值
driver = pro.getProperty("driver");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
// 註冊驅動
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 獲取連接對象
* @return 返回連接對象
*/
public static Connection getConn() throws SQLException {
return DriverManager.getConnection(url,username,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 rs
* @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();
}
}
}
}
事務管理
- 事務:一個包含多個步驟的業務操作。如果這個業務操作被事務管理,則這多個步驟要麼同時成功,要麼同時失敗。
- 操作:
- 開啟事務
- 提交事務
- 回滾事務
- 使用Connection對象來管理事務
- 開啟事務:setAutoCommit(boolean autoCommit) :調用該方法設置參數為false,即開啟事務
- 在執行sql之前開啟事務
- 提交事務:commit()
- 當所有sql都執行完提交事務
- 回滾事務:rollback()
- 在catch中回滾事務
測試:
public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt1 = null; PreparedStatement pstmt2 = null; try { // 1.創建sql,轉賬的sql String sql1 = "UPDATE ACCOUNT SET BALANCE = BALANCE - ? WHERE ID = ?"; String sql2 = "UPDATE ACCOUNT SET BALANCE = BALANCE + ? WHERE ID = ?"; // 2.獲取連接對象 conn = JDBCUtils.getConn(); // 開啟事務 conn.setAutoCommit(false); // 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) { if(conn != null) { try { // 事務回滾 conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } e.printStackTrace(); } finally { JDBCUtils.close(pstmt1,conn); JDBCUtils.close(pstmt2,null); } }
- 開啟事務:setAutoCommit(boolean autoCommit) :調用該方法設置參數為false,即開啟事務