資料庫事務
1)在資料庫中,所謂事務是指一組邏輯操作單元,使資料從一種狀态變換到另一種狀态。
2)為確定資料庫中資料的一緻性,資料的操縱應該是離散的成組的邏輯單元:當它全部完成時,資料的一緻性可以保持,而當這個單元中的一部分操作失敗,整個事務應全部視為錯誤,所有從起始點以後的操作應全部回退到開始狀态
3)事務的操作:先定義開始一個事務,然後對資料做修改操作,這時如果送出(COMMIT),這些修改就永久地儲存下來,如果回退(ROLLBACK),資料庫管理系統将放棄所做的所有修改而回到開始事務時的狀态。
4)事務的ACID(acid)屬性
原子性:原子性是指事務是一個不可分割的工作機關,事務中的操作要麼都發生,要麼都不發生。
一緻性:事務必須使資料庫從一個一緻性狀态變換到另外一個一緻性狀态
隔離性:事務的隔離性是指一個事務的執行不能被其他事務幹擾,即一個事務内部的操作及使用的資料對兵法的其他事務是隔離的,并發執行的各個事務之間不能互相幹擾
持久性:持久性是指一個事務一旦被送出,它對資料庫中資料的改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響
JDBC 事務處理
1)事務:指構成單個邏輯工作單元的操作集合
2)事務處理:保證所有事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操作時,要麼所有的事務都被送出(commit),要麼整個事務復原(rollback)到最初狀态
3)當一個連接配接對象被建立時,預設情況下是自動送出事務:每次執行一個SQL語句時,如果執行成功,就會向資料庫自動送出,而不能復原
4)為了讓多個SQL語句作為一個事務執行:
- 調用Connection對象的setAutoCommit(false);以取消自動送出事務
- 在所有的SQL語句都成功執行後,調用commit()方法送出事務
- 在出現異常時,調用rollback()方法復原事務
舉個例子
public class JDBCTest04 {
/**
* 違反事務一緻性
* A 給 B 彙款 500 元
*/
public void testTransaction() throws SQLException, ClassNotFoundException {
String driverClass = "com.mysql.jdbc.Driver";
String jdbcurl = "";
Connection connection = null;
Class.forName(driverClass);
connection = DriverManager.getConnection(jdbcurl,"user","password");
PreparedStatement preparedStatement = null;
String sql = "UPDATE users SET balance = " + "balance - 500 WHERE id = 1"; // A 賬号 - 500
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();
int i = 10 / 0; // 第一條sql執行完成A賬号-500後,執行到這裡報錯導緻第二條sql沒有執行,進而違反了資料的一緻性
System.out.println(i);
sql = "UPDATE users SET balance = " + "balance + 500 WHERE id = 2";// B 賬号 + 500
connection = DriverManager.getConnection(jdbcurl,"user","password");
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();
}
}
複制
public class JDBCTest04 {
/**
* 保證事務一緻性
* A 給 B 彙款 500 元
* 1. 如果多個操作,每個操作使用的是自己的單獨的連接配接,則無法保證事務
* 2. 具體步驟:
* 1)事務操作開始前,開始事務:取消connection的預設送出行為
* connection.setAutoCommit(false)
* 2)如果事務的操作都成功,則送出:connection.commit();
* 3)復原事務:若出現異常,則在catch塊中復原事務
*/
public void testTransaction01() throws SQLException {
String driverClass = "com.mysql.jdbc.Driver";
String jdbcurl = "";
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
Class.forName(driverClass);
connection = DriverManager.getConnection(jdbcurl,"user","password");
connection.setAutoCommit(false);
String sql = "UPDATE users SET balance = " + "balance - 500 WHERE id = 1";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();
int i = 10 / 0;
sql = "UPDATE users SET balance = " + "balance + 500 WHERE id = 2";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();
connection.commit();
}catch (Exception e){
e.printStackTrace();
try {
connection.rollback();
}catch (Exception e1){
e.printStackTrace();
}
}finally {
preparedStatement.close();
connection.close();
}
}
}
複制