# 事務 - **基本介紹** 1. JDBC 程式中當一個Connection對象創建時,預設情況下是自動提交事務:每次執行一個 SQL 語句時,如果執行成功,就會向資料庫自動提交,而不能回滾。 2. JDBC程式中為了多個SQL語句作為一個整體執行,需要==使用事務==。 3. 調用 Conne ...
事務
-
基本介紹
- JDBC 程式中當一個Connection對象創建時,預設情況下是自動提交事務:每次執行一個 SQL 語句時,如果執行成功,就會向資料庫自動提交,而不能回滾。
- JDBC程式中為了多個SQL語句作為一個整體執行,需要使用事務。
- 調用 Connection 的 setAutoCommit(false) 可以取消自動提交事務(相當與開啟了事務)。
- 在所有的 SQL 語句都成功執行後,調用 commit(); 方法提交事務。
- 在其中某個操作失敗或出現異常時,調用 rollback(); 方法回滾事務。
-
案例:模擬經典的轉賬的業務
MySQL代碼:
CREATE TABLE account( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(32) NOT NULL DEFAULT '', balance DOUBLE NOT NULL DEFAULT 0 ) CHARACTER SET utf8; INSERT INTO account VALUES(NULL, '馬雲', 3000); INSERT INTO account VALUES(NULL, '馬化騰', 10000); SELECT * FROM account;
Java代碼:
package com.hspedu.jdbc.transaction_; import com.hspedu.jdbc.utils.JDBCUtils; import org.junit.jupiter.api.Test; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /** * Description: 演示在jdbc 中如何使用事務 */ public class Transaction_ { //沒有使用事務,模擬銀行轉賬出現異常 @Test public void noTransaction(){ //1. 得到連接 Connection connection = null; //預設情況下,connection 預設自動提交, 執行一句sql語句,就會提交事務 //2. SQL語句 String sql = "update account set balance = balance - 100 where id = ?"; String sql2 = "update account set balance = balance + 100 where id = ?"; PreparedStatement preparedStatement = null; //3. 創建PreparedStatement 對象 try { connection = JDBCUtils.getConnection(); preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1, 1); preparedStatement.executeUpdate(); int i = 1 / 0; //拋出異常接下來的語句就不會執行 preparedStatement = connection.prepareStatement(sql2); preparedStatement.setInt(1, 2); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { //關閉資源 JDBCUtils.close(null, preparedStatement, connection); } } //使用事務 @Test public void UseTransaction() { //1. 得到連接 Connection connection = null; //預設情況下,connection 預設自動提交, 執行一句sql語句,就會提交事務 //2. SQL語句 String sql = "update account set balance = balance - 100 where id = ?"; String sql2 = "update account set balance = balance + 100 where id = ?"; PreparedStatement preparedStatement = null; //3. 創建PreparedStatement 對象 try { connection = JDBCUtils.getConnection(); connection.setAutoCommit(false);//相當與開啟了事務 preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1, 1); preparedStatement.executeUpdate(); int i = 1 / 0; //拋出異常接下來的語句就不會執行 preparedStatement = connection.prepareStatement(sql2); preparedStatement.setInt(1, 2); preparedStatement.executeUpdate(); //這裡提交事務 connection.commit(); } catch (SQLException | ArithmeticException e) { System.out.println("執行發生了異常,撤銷執行的SQL"); e.printStackTrace(); //可以在這裡進行回顧,即撤銷執行的sql語句 try { connection.rollback();//預設回滾到事務開始的時候,可以填入回滾點savePoint } catch (SQLException ex) { throw new RuntimeException(ex); } } finally { //關閉資源 JDBCUtils.close(null, preparedStatement, connection); } } }
-
模擬1號向2號轉賬100元轉賬異常,調用noTransaction()方法,不使用事務,可以發現結果如下:
發生異常後,1號的存款轉出了 100元,2號沒有收到100元,100元沒了。
-
如果調用的是useTransaction()方法,使用事務(connection.setAutoCommit(false) 取消事務自動提交)結果如下:
沒有變化,控制台列印了 “執行發生了異常,撤銷執行的SQL”,出現了異常後try-catch併進行了事務的回滾
-