Skip to content

Latest commit

 

History

History
133 lines (114 loc) · 3.95 KB

事務的四大特性.md

File metadata and controls

133 lines (114 loc) · 3.95 KB

事務的四大特性

四大特性(ACID)

  • 原子性(Atomicity): 事務中所有操作是不可再分割的原子單位。事務中所有操作要嘛全部執行成功,要嘛全部執行失敗。
  • 一致性(Consistency): 事務執行後,數據庫狀態與其他業務規則保持一致。如轉帳業務,無論事務執行成功與否,餐與轉帳的兩個帳號餘額之河應該是不變得。
  • 隔離性(Isolation): 隔離性是指在併發操作中,不同事務之間應該隔離開來,使每個併發中的事務不會相互干擾。
  • 持久性(Durability): 一旦事務提交成功,事務中所有的數據操作都必須被持久化到數據庫中,即使提交事務後,數據庫馬上崩潰,再數據庫重啟時,也必須能保證通過某種機制恢復數據。

MySQL 中的事務

MySQL 每執行一條SQL語句,都是一個單獨的事務。如果需要再一個事務中包含多條 SQL 語句,那麼需要開啟事務和結束事務。

  • 開啟事務: start transaction;
  • 結束事務: commitrollback;
    • commit 表示提交,即事務中的多條 SQL 語句所做出的影響會持久化到數據庫中。
    • rollback: 表示回滾,即回滾到事務的起點,之前做的所有操作都被撤銷。

JDBC 中的事務

在 jdbc 中處理事務,都是通過 Connection 完成。 同一事務中所有的操作,都在使用同一個 Connection 對象。 Connection 的三個方法與事務相關:

  • setAutoCommit(boolean): 設置是否為自動提交事務,如果 true(默認值就是 true) 表示自動提交(代表沒有事務),也就是每條執行的 SQL 語句都是一個單獨的事務,如果設置 false, 那麼就相當於開啟事務。con.setAutoCommit(false) 表示開啟事務。
  • commit(): 提交結束事務。con.commit() 表示提交事務。
  • rollback(): 回滾結束事務。con.rollback() 表示回滾事務。
  • jdbc 處理事務的代碼格式:
try {
    con.setAutoCommit(false); //開啟事務
    ...
    ...
    con.commit(); //try 的最後提交事務
} catch(Exception e) {
    con.rollback(); //回滾事務
}

Example

//AccountDao.java
import java.sql.Connection;
import java.sql.PreparedStatement;

import demo3.JdbcUtils;

public class AccountDao {
	/**
	 * 修改指定用戶的餘額
	 * @param name
	 * @param balance
	 */
	public void updateBalance(Connection con, String name, double balance) {
		try {
			/*
			 * 1. 給出 sql 模板,創建 pstmt
			 */
			String sql = "UPDATE account SET balance=balance+? where name=?";
			PreparedStatement pstmt = con.prepareStatement(sql);
			/*
			 * 2. 對參數進行賦值
			 */
			pstmt.setDouble(1, balance);
			pstmt.setString(2, name);
			/*
			 * 3. 執行
			 */
			pstmt.executeUpdate();
		} catch(Exception e) {
			throw new RuntimeException(e);
		}
	}
}

//Demo.java
import java.sql.Connection;
import java.sql.SQLException;

import org.junit.Test;

import demo3.JdbcUtils;

/**
 * 演示轉帳
 * @author jack870131
 * 
 * 所有對 Connection 的操作都在 service 層處理
 */
public class Demo6 {
	/**
	 * 轉帳
	 * @param from
	 * @param to
	 * @param money
	 * @throws SQLException 
	 */
	public void transfer(String from, String to, double money) throws SQLException {
		//對事務的操作必須使用 Connection 對象
		Connection con = null;
		try {
			con = JdbcUtils.getConnection();
			//開啟事務
			con.setAutoCommit(false);
			
			AccountDao dao = new AccountDao();
			dao.updateBalance(con, from, -money); //給 from 減去相應金額
			
			if(true) {
				throw new RuntimeException();
			}
			
			dao.updateBalance(con, to, +money); //給 to 加上相應金額
			
			//提交事務
			con.commit();
			con.close();
		} catch(Exception e) {
			//回滾事務
			try {
				con.rollback();
				con.close();
			} catch (SQLException e1) {
				throw new RuntimeException(e);
			}
		}
	}
	
	@Test
	public void fun1() throws SQLException {
		transfer("jack", "vivian", 100);
	}
}