天天看點

java處理mysql中的事務及SavePoint的用法

事務(Transaction)是通路并可能更新資料庫中各種資料項的一個程式執行單元(unit)。事務通常由進階資料庫操縱語言或程式設計語言

(如SQL,C++或Java)書寫的使用者程式的執行所引起,并用形如begin transaction和end transaction語句(或函數調用)來界定。

事務由事務開始(begin transaction)和事務結束(end transaction)之間執行的全體操作組成。

例如:在關系資料庫中,一個事務可以是一條SQL語句,一組SQL語句或整個程式。

我對事務的了解最深的還是原子性;即,要麼全部操作成功,要麼都失敗。

在資料庫操作中,有時候一個功能的實作要涉及到多個表的操作,我們就以此為一個事務,必須保證多個表的變化都執行,

那麼該怎麼處理呢?

在這裡以java、mysql資料庫為例,銀行轉賬問題(事務)

事務描述:使用者a給使用者b彙款x,資料庫表中會有兩個操作,a使用者的賬目數減少x,b使用者賬目數增加x。

隻有當b使用者收到錢時,兩個操作才回執行,否則都不執行,兩人賬戶不變。

模拟操作:

public class BankExample {

	private static String conStr = "jdbc:mysql://localhost/test";
	private String root = "root";
	private String pwd = "123";
	
	static{
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public Connection getCon(){
		try {
			return DriverManager.getConnection(conStr, root, pwd);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static void main(String[] args) {
		BankExample be = new BankExample();
		
		Connection con = null;
		Savepoint sp = null;
		int x = 0;
		try {
			con = be.getCon();
			con.setAutoCommit(false);//設定自動遞交關閉
			//操作一 a使用者減去x
			String sql = "insert into a_bank values(null,?)";
			PreparedStatement pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, 1000 - x);
			pstmt.executeUpdate();
			
			//操作二 b使用者 加上 x
			String sql1 = "insert into b_bank values(null,?)";
			PreparedStatement pstmt1 = con.prepareStatement(sql1);
			pstmt1.setInt(1, 1000 + x);
			pstmt1.executeUpdate();
			
			sp = con.setSavepoint();//設定斷點
			
			//列印憑條
			PreparedStatement ps = con.prepareStatement("seltct * from result id=?");
			ps.setString(1, "33");
			ResultSet rs = ps.executeQuery();
			System.out.println(rs.getString("name"));
			
		} catch (SQLException e) {
			try {
				con.rollback(sp);//滾回斷點
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
		try {
			con.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
           

保證一個事務的原子性的方法就是統一送出setAutoCommit(false),此方法隻有當調用commit()方法之後才會送出,

進而保證事務的原子性。

我在上面加了一個列印憑條的例子,以便了解SavePoint,不管有沒有憑條轉賬都可以完成,是以轉賬和列印憑條是兩個事務,

我在列印憑條的操作之前設定一個儲存點SavePoint,如果沒有憑條了會抛出SQLException異常,我在此處理儲存點讓進度”滾回到“

設定的地方然後執行就可以了!