事務使指一組最小邏輯操做單元,裏面有多個操做組成。 組成事務的每一部分必需要同時提交成功,若是有一個操做失敗,整個操做就回滾。sql
事務ACID特性:數據庫
l 原子性(Atomicity)併發
原子性是指事務是一個不可分割的工做單位,事務中的操做要麼都發生,要麼都不發生。 spa
l 一致性(Consistency設計
事務必須使數據庫從一個一致性狀態變換到另一個一致性狀態。code
l 隔離性(Isolation)對象
事務的隔離性是多個用戶併發訪問數據庫時,數據庫爲每個用戶開啓的事務,不能被其餘事務的操做數據所幹擾,多個併發事務之間要相互隔離。blog
l 持久性(Durability)事務
持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即便數據庫發生故障也不該該對其有任何影響ci
需求: 張三給李四轉帳
設計: 帳戶表
技術:
|-- Connection
savepoint
- 要回滾到的 Savepoint
對象
1:sql代碼,帳目表:
1 CREATE TABLE transfer( 2 id INT PRIMARY KEY AUTO_INCREMENT , 3 accName VARCHAR(20), 4 accmoney DOUBLE 5 )
2:設定事務,若事務中有語句出現錯誤,則回滾到事務的初始化
1 /** 2 * 這是個事務的操做類 3 * 4 * @author LZL 5 * 6 */ 7 public class Connection_false { 8 9 // 設定全局變量 10 private static Connection conn; 11 private static PreparedStatement stsm; 12 13 /** 14 * 這是個出錯就回滾回整個事務的起始未知的例子 15 */ 16 17 @Test 18 public void trans1() { 19 20 // 1:準備sql語言 21 String sql1 = "UPDATE transfer SET accmoney=accmoney-1000 WHERE accName='張三';"; 22 String sql2 = "UPDATE transfer SET accmoney=accmoney+1000 WHERE accName='李四';"; 23 24 try { 25 // 2:建立鏈接 26 conn = Jdbcutil.getConnection(); 27 28 // 3:設定事物爲手動開啓 29 // void setAutoCommit(boolean autoCommit):將此鏈接的自動提交模式設置爲給定狀態 30 conn.setAutoCommit(false); 31 32 // 4:執行sql 33 stsm = conn.prepareStatement(sql1); 34 stsm.executeUpdate(); 35 36 stsm = conn.prepareStatement(sql2); 37 stsm.executeUpdate(); 38 39 } catch (Exception e) { 40 // 4:如果上面的語句有任何一條出錯,則回滾事務 41 try { 42 conn.rollback(); 43 } catch (Exception e1) { 44 e1.printStackTrace(); 45 } 46 } finally { 47 // 4:如果上面的語句(事務)都沒錯,則執行事務 48 // void commit():使全部上一次提交/回滾後進行的更改爲爲持久更改,並釋放此 Connection 49 // 對象當前持有的全部數據庫鎖。 50 try { 51 conn.commit(); 52 // 5:關閉鏈接 53 Jdbcutil.close(conn, stsm); 54 } catch (Exception e) { 55 e.printStackTrace(); 56 } 57 58 } 59 }
3:這是個回滾到事務中的指定位置的方法 例:若是我知道第一筆轉帳確定成功,若出錯就只會是第二筆出錯,因此我會在第一和第二之間的位置設定個保存點:
Savepoint setSavepoint(String name) 在當前事務中建立一個具備給定名稱的保存點
而後如果出錯,則回滾到該保存點的位置,而以前的語句仍正常執行 void rollback(Savepoint savepoint):
savepoint - 要回滾到的 Savepoint 對象
1 @Test 2 public void test2() { 3 4 // 建立保存點對象 5 Savepoint one = null; 6 7 // 1:設定sql語句 8 // 第一次轉帳 9 String one1 = "UPDATE transfer SET accmoney=accmoney-1000 WHERE accName='張三';"; 10 String one2 = "UPDATE transfer SET accmoney=accmoney+1000 WHERE accName='李四';"; 11 // 第二次轉帳 12 String two1 = "UPDATE transfer SET accmoney=accmoney-1000 WHERE accName='張三';"; 13 String two2 = "UPDATE tranfer SET accmoney=accmoney+1000 WHERE accName='李四';"; 14 15 try { 16 // 2:建立鏈接 17 conn = Jdbcutil.getConnection(); 18 19 // 3:設定事務爲手動執行 20 conn.setAutoCommit(false); 21 22 // 4:建立PreparedStatement對象。執行sql語句 23 // 執行第一筆轉帳 24 stsm = conn.prepareStatement(one1); 25 stsm.executeUpdate(); 26 stsm = conn.prepareStatement(one2); 27 stsm.executeUpdate(); 28 29 // 5:設定保存點 30 one = conn.setSavepoint("one"); 31 32 // 執行第二筆轉帳 33 stsm = conn.prepareStatement(two1); 34 stsm.executeUpdate(); 35 stsm = conn.prepareStatement(two2); 36 stsm.executeUpdate(); 37 38 } catch (Exception e) { 39 // 6:如有語句出錯,則回滾到保存點 40 try { 41 conn.rollback(one); 42 } catch (Exception e1) { 43 e1.printStackTrace(); 44 } 45 e.printStackTrace(); 46 } finally { 47 try { 48 // 7:若語句沒有錯誤,則執行事務 49 conn.commit(); 50 // 8:關閉鏈接 51 Jdbcutil.close(conn, stsm); 52 } catch (Exception e) { 53 e.printStackTrace(); 54 } 55 } 56 57 }