JDBC中處理事務,小Demo
事務的四大特性(ACID):
原子性(Atomicity):事務中所有操作是不可再分割的原子單位。事務中所有操作要麼全部執行成功,要麼全部執行失敗。
一致性(Consistency):事務執行後,資料庫狀態與其它業務規則保持一致。如轉賬業務,無論事務執行成功與否,參與轉賬的兩個賬號餘額之和應該是不變的。
隔離性(Isolation):隔離性是指在併發操作中,不同事務之間應該隔離開來,使每個併發中的事務不會相互干擾。
永續性(Durability):一旦事務提交成功,事務中所有的資料操作都必須被持久化到資料庫中,即使提交事務後,資料庫馬上崩潰,在資料庫重啟時,也必須能保證通過某種機制恢復資料。
在預設情況下,每執行一條SQL語句,都是一個單獨的事務。如果需要在一個事務中包含多條SQL語句,那麼需要開啟事務和結束事務。
開啟事務:start transaction;
結束事務:commit或rollback。
在執行SQL語句之前,先執行strat transaction,這就開啟了一個事務(事務的起點),然後可以去執行多條SQL語句,最後要結束事務,commit表示提交,即事務中的多條SQL語句所做出的影響會持久化到資料庫中。或者rollback,表示回滾,即回滾到事務的起點,之前做的所有操作都被撤消了!
Connection的三個方法與事務相關:
(1) setAutoCommit(boolean):設定是否為自動提交事務,如果true(預設值就是true)表示自動提交,也就是每條執行的SQL語句都是一個單獨的事務。
如果設定false,那麼就相當於開啟了事務了;con.setAutoCommit(false)表示開啟事務。
(2) commit():提交結束事務;con.commit();表示提交事務。
(3) rollback():回滾結束事務。con.rollback();表示回滾事務。
jdbc處理事務的程式碼格式:
try { con.setAutoCommit(false);//開啟事務… …. … con.commit();//try的最後提交事務 } catch() { con.rollback();//回滾事務 }
首先做一些準備工作:
(2)在資料庫中建立表account,並且插入資料
create table account
(
id int,
balance int,
)
select * from account
insert into account values (1,1000)
insert into account values (2,1000)
如圖所示:
在程式中,首先是程式沒有發生異常,則,轉賬成功。
當程式發生異常時,查詢資料庫,則會發現轉賬操作並沒有完成。符合ACID特性。
Demo程式碼展示:
package com.ywq;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Dao {
/**
* 修改指定使用者的餘額!
* @param ct
* @param id
* @param balance
*/
//同一事務中必須使用同一個Connection物件,所以此處的Connection物件由呼叫處傳入。
public void updateBalance(Connection ct,int id,int balance){
try {
String sql="update account set balance=balance+? where id=?";
PreparedStatement pt=ct.prepareStatement(sql);
pt.setInt(1, balance);
pt.setInt(2, id);
pt.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
package com.ywq;
import java.sql.*;
public class Demo {
public static void main(String[] args) {
zhuanZhang(1, 2, 100);
}
public static void zhuanZhang(int from, int to, int money) {
// 對事務的操作必須使用Connection物件!
Connection ct = null;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
ct=DriverManager.getConnection("jdbc:odbc:ywq");
System.out.println(ct);
//開啟事務
ct.setAutoCommit(false);
Dao dao = new Dao();
dao.updateBalance(ct, from, -money);//給from減去相應金額
if(true) {
//把此處的if語句塊註釋掉,則轉賬成功 throw new RuntimeException("不好意思,此處發生了異常,但是轉賬操作進行了一半,請觀察結果");
}
dao.updateBalance(ct, to, money);//給to加上相應金額
//提交事務
ct.commit();
ct.close();
} catch(Exception e) {
//回滾事務
try {
ct.rollback();
ct.close();
} catch (SQLException e1) {
}
throw new RuntimeException(e);
}
}
}