1. 程式人生 > >JDBC中處理事務,小Demo

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);
		}
	}
	

}