事務簡介
數據庫事務(Database Transaction) ,是指作為單個邏輯工作單元執行的一系列操作,要么完全地執行,要么完全地不執行。
事務是必須滿足4個條件(ACID)
- 事務的原子性( Atomicity):一組事務,要么全部成功;要么全部失敗。
- 一致性 (Consistency):事務在完成時,必須使所有的數據都保持一致狀態。在相關數據庫中,所有規則都必須應用於事務的修改,以保持所有數據的完整性。比如一個學生表中新插入了一條記錄,這個學生的class_id必須是一個已經存在的正確的,A賬戶向B賬戶轉賬,不能出現負數,如果不做任何保障,出現了負數,這就是破壞了一致性可以認為是一致性表示數據本來是正確的,經過了事務,轉換為了另外的一個狀態,仍舊是正確的。
- 隔離性(Isolation):由並發事務所作的修改必須與任何其它並發事務所作的修改隔離。也就是說另一並發事務要么讀取的是事務前的狀態,要么是事務后的狀態,不會是這個事務的中間狀態。
- 持久性(Durability):事務完成之后,它對於系統的影響是永久性的。該修改即使出現致命的系統故障也將一直保持。
在默認情況下,MySQL每執行一條SQL語句,都是一個單獨的事務
如果需要將多條SQL語句設在在同一個事務中,那么需要開啟事務和結束事務
JDBC中與事務有關的方法
Connection與事務有關的主要方法:
- setAutoCommit(boolean):設置是否為自動提交事務,如果true(默認值為true)表示自動提交,也就是每條執行的SQL語句都是一個單獨的事務;如果設置為false,那么相當於開啟了事務,con.setAutoCommit(false) 表示開啟事務。
- commit():提交結束事務。
- rollback():回滾結束事務。
- setSavepoint():設置保存點。
事務使用示例
package jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class MyTransactional { public static void main(String[] args) throws Exception{ String user = "root"; String password = "123456"; String url = "jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8"; //2、獲取連接對象 Connection conn = DriverManager.getConnection(url, user, password); String sql = "delete from student where id='59'"; //2、獲得sql語句執行對象 Statement stmt = conn.createStatement(); conn.setAutoCommit(false); //3、執行並保存結果集 int rows = stmt.executeUpdate(sql); System.out.println("受影響的行: "+rows); conn.commit(); // conn.rollback(); conn.close(); stmt.close(); } }
在執行前開啟事務,conn.setAutoCommit(false);
注意:一定是執行前
只有開啟事務和結束事務之間的執行才屬於這個事務,如果像下面這樣,可以認為是兩個事務,前面一個自動提交了,然后開啟了新的事務,然后回滾了新的事務
stmt.executeUpdate(sql); conn.setAutoCommit(false); conn.rollback();
最終通過commit或者rollback 結束事務。
通常的一個使用形式為:
try { con = DBConnection.getConnection(); //開啟事務 con.setAutoCommit(false); //處理業務邏輯 //提交事務 con.commit(); } catch (SQLException e) { e.printStackTrace(); //出現異常,回滾事務 try { con.rollback(); System.out.println("JDBC Transaction rolled back successfully"); } catch (SQLException e1) { System.out.println("SQLException in rollback" + e.getMessage()); } }
保存點
有的時候可能並不需要將一整個事務進行回滾,一個復雜的事務可能由幾個一致性的階段組成
保存點就是在一個事務中,插入幾個還原點,再出現問題時,可以及時的撤回到這個地方來
當撤回到一個還原點時,事務還在,仍在進行中,所以還需要再次的COMMIT,這次的COMMIT,保存點以下的執行相當於不存在。
package jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Savepoint; import java.sql.Statement; public class MyTransactional { public static void main(String[] args) throws Exception{ String user = "root"; String password = "123456"; String url = "jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8"; //2、獲取連接對象 Connection conn = DriverManager.getConnection(url, user, password); conn.setAutoCommit(false); String sql1 = "delete from student where id='158'"; String sql2 = "delete from student where id='159'"; //2、獲得sql語句執行對象 Statement stmt = conn.createStatement(); //3、執行並保存結果集 stmt.executeUpdate(sql1); Savepoint savepoint1 = conn.setSavepoint("savepoint1"); stmt.executeUpdate(sql2); Savepoint savepoint2 = conn.setSavepoint("savepoint2"); conn.rollback(savepoint1); conn.commit(); // conn.rollback(); conn.close(); stmt.close(); } }
上面的示例中,執行了兩次刪除,刪除id=158時,創建保存點savepoint1;刪除id=159時,創建保存點savepoint2
將事務回滾到保存點1 conn.rollback(savepoint1);,然后進行提及,保存點savepoint1以上的部分成功提交,后面的部分沒有提交
也就是回滾到哪個保存點,那個保存點以下就相當於不存在
保存點就是這樣將一整個完整的過程進行了拆分,rollback到哪個保存點,哪個保存點以下就會回滾,之前的就會提交
一定要注意: conn.rollback(savepoint1); 並不會結束事務,只有 conn.commit();或者 conn.rollback();方法才會結束事務。
原文地址:
JDBC事務與保存點 JDBC簡介(七)