JDBC學習(六、事務處理操作)
阿新 • • 發佈:2019-02-15
案例:銀行轉賬:從張無忌賬戶上給趙敏轉1000塊。
準備:account(賬戶表):
---------------------------------------------------------------
id name(賬號,唯一) balance(餘額)
1 張無忌 20000
2 趙敏 0
---------------------------------------------------------------
操作步驟:
1):檢查張無忌的賬戶餘額是否大於等於1000.
SELECT * FROM account WHERE name = '張無忌' AND balance >= 1000;
2):從張無忌的賬戶餘額中減少1000.
UPDATE account SET balance = balance - 1000 WHERE name = '張無忌';
3):再在趙敏的賬戶餘額中增加1000.
UPDATE account SET balance = balance + 1000 WHERE name = ' 趙敏';
如果:在第二步和第三步之間如果程式中斷,怎麼辦? (通過異常來模擬)
在資料庫中,所謂事務是指一組邏輯操作單元,使資料從一種狀態變換到另一種狀態。
我們把多個密不可分的操作看做是一個整體,那麼該整體就稱之為一個事務.
--------------------------------------------------
事務的ACID屬性:
1. 原子性(Atomicity)原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
2. 一致性(Consistency)事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態,但是不最終資料不能被破壞,兩個賬戶的總餘額是不能改變的.
3. 隔離性(Isolation) :MySQL再講
事務的隔離性是指一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。
4. 永續性(Durability)永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響
--------------------------------------------------
事務:指構成單個邏輯工作單元的操作集合
事務處理:保證所有事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操作時,要麼所有的事務都被提交(commit),要麼整個事務回滾(rollback)到最初狀態
處理事務的兩個動作:
提交:commit: 當整個事務中,所有的邏輯單元都正常執行成功. ---->提交事務.---資料已經提交,不能更改.
回滾:rollback: 當整個事務中,有一個邏輯單元執行失敗, ---->回滾事務.
撤銷該事務中的所有操作,釋放鎖--->恢復到最初的狀態.
準備:account(賬戶表):
---------------------------------------------------------------
id name(賬號,唯一) balance(餘額)
1 張無忌 20000
2 趙敏 0
---------------------------------------------------------------
操作步驟:
1):檢查張無忌的賬戶餘額是否大於等於1000.
SELECT * FROM account WHERE name = '張無忌' AND balance >= 1000;
2):從張無忌的賬戶餘額中減少1000.
UPDATE account SET balance = balance - 1000 WHERE name = '張無忌';
3):再在趙敏的賬戶餘額中增加1000.
UPDATE account SET balance = balance + 1000 WHERE name = ' 趙敏';
如果:在第二步和第三步之間如果程式中斷,怎麼辦? (通過異常來模擬)
程式碼演示:
事務(Transaction,簡寫為tx):public void test1(){ String sql = "select * from account where name=? AND balance>?"; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","rootroot"); System.out.println(conn); //1.查詢張無忌賬戶餘額是否大於1000 PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, "張無忌"); ps.setDouble(2, 1000.0); ResultSet rs = ps.executeQuery(); if(!rs.next()){ throw new RuntimeException("賬戶餘額不足"); } //2.從張無忌賬戶中轉出1000 sql = "update account set balance=balance-? where name=?"; ps = conn.prepareStatement(sql); ps.setDouble(1, 1000.0); ps.setString(2, "張無忌"); ps.executeUpdate(); //---------模擬停電了-------------- //int a = 1/0; //-------------------------- //3.從趙敏賬戶中增加1000 sql = "update account set balance=balance+? where name=?"; ps = conn.prepareStatement(sql); ps.setDouble(1, 1000.0); ps.setString(2, "趙敏"); ps.executeUpdate(); } catch (ClassNotFoundException |SQLException |RuntimeException ex) { ex.printStackTrace(); } }
在資料庫中,所謂事務是指一組邏輯操作單元,使資料從一種狀態變換到另一種狀態。
我們把多個密不可分的操作看做是一個整體,那麼該整體就稱之為一個事務.
--------------------------------------------------
事務的ACID屬性:
1. 原子性(Atomicity)原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
2. 一致性(Consistency)事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態,但是不最終資料不能被破壞,兩個賬戶的總餘額是不能改變的.
3. 隔離性(Isolation)
事務的隔離性是指一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。
4. 永續性(Durability)永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響
--------------------------------------------------
事務:指構成單個邏輯工作單元的操作集合
事務處理:保證所有事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操作時,要麼所有的事務都被提交(commit),要麼整個事務回滾(rollback)到最初狀態
處理事務的兩個動作:
提交:commit: 當整個事務中,所有的邏輯單元都正常執行成功. ---->提交事務.---資料已經提交,不能更改.
回滾:rollback: 當整個事務中,有一個邏輯單元執行失敗, ---->回滾事務.
撤銷該事務中的所有操作,釋放鎖--->恢復到最初的狀態.
1):預設情況下,在JDBC中執行DML操作就會自動提交事務,此時我們得設定事務的手動提交機制(取消事務的自動提交).
2):查詢操作,不涉及資料的更改,所以不需要事務.
3):MySQL中InnoDB儲存引擎支援事務,MyISAM不支援.
alter table account engine = 'MyISAM'; ---> "InnoDB"
意識:如果是DML操作時,沒有異常,程式碼也正確,但是資料改變不了,首先去想到事務沒有提交。
操作事務的模板:
try{
//取消事務自動提交:
connection物件.setAutoCommit(false);
操作1
操作2
操作3
//提交事務
Connection物件.commit();
}catch(Exception e){
//處理異常
//回滾事務
Connection物件.rollback();
}finally{
釋放資源
}
上述例子修改後程式碼演示:
@Test
public void test2() throws ArithmeticException{
String sql = "select * from account where name=? AND balance>?";
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","rootroot");
//取消事務自動提交
conn.setAutoCommit(false);
System.out.println(conn);
//1.查詢張無忌賬戶餘額是否大於1000
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "張無忌");
ps.setDouble(2, 1000.0);
ResultSet rs = ps.executeQuery();
if(!rs.next()){
throw new RuntimeException("賬戶餘額不足");
}
//2.從張無忌賬戶中轉出1000
sql = "update account set balance=balance-? where name=?";
ps = conn.prepareStatement(sql);
ps.setDouble(1, 1000.0);
ps.setString(2, "張無忌");
ps.executeUpdate();
//---------模擬停電了--------------
int a = 1/0;
//--------------------------
//3.從趙敏賬戶中增加1000
sql = "update account set balance=balance+? where name=?";
ps = conn.prepareStatement(sql);
ps.setDouble(1, 1000.0);
ps.setString(2, "趙敏");
ps.executeUpdate();
conn.commit();
} catch ( Exception ex) {
ex.printStackTrace();
try {
conn.rollback();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}