JDBC複習--資料庫事務
阿新 • • 發佈:2020-12-21
技術標籤:JDBC學習
此部落格僅為本人學習JDBC時所做記錄。
08-資料庫事務
8.1 事務
一組邏輯操作單元,使資料從一種狀態變換到另一種狀態。
一組邏輯操作單元,一個或多個DML操作
8.2 事務處理的原則
保證所有事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。
當在一個事務中執行多個操作時,要麼所有的事務都被提交(commit),那麼這些修改就永久地儲存下來;要麼資料庫管理系統將放棄所作的所有修改,整個事務回滾(rollback)到最初狀態。
說明:
資料一旦提交,就不回滾
哪些操作會導致資料的自動提交
- DDL操作一旦執行,都會自動提交
- set autocommit =false 對DDL操作失效
- DML預設情況下,一旦執行,就會自動提交
- 我們可以通過set autocommit = false 的方式取消DML操作的自動提交
- 預設在關閉連線時,會自動提交資料
8.3 程式碼的體現
@Test
public void testUpdateWithTx() {
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
System.out.println(conn.getAutoCommit());
// 取消資料的自動提交
conn.setAutoCommit(false);
String sql1 = "update user_table set balance = balance-100 where user = ?";
update(conn,sql1,"AA");
// 模擬網路異常
System.out.println(10/0);
String sql2 = "update user_table set balance = balance+100 where user = ?" ;
update(sql2,"BB");
System.out.println("轉賬成功");
// 提交資料
conn.commit();
} catch (Exception e) {
e.printStackTrace();
// 回滾
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} finally {
//修改為自動提交資料
//主要針對於使用資料庫連線池的使用
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
JDBCUtils.closeResource(conn,null);
}
}
8.4 通用的增刪改操作(考慮事務)
//通用的增刪改操作 ----version2.0
public int update(Connection conn,String sql,Object ...args){//sql中佔位符的個數應該與可變形參args的個數一致
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
for (int i=0;i<args.length;i++)
{
ps.setObject(i+1,args[i]);//注意i+1
}
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(null,ps);
}
return 0;
}
8.5 通用的查詢(考慮事務)
//通用的查詢操作,用於返回資料表中的一條記錄(version 2.0:考慮上事務)
public <T> T getInstance(Connection conn,Class<T> clazz,String sql,Object ...args) {
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
for (int i=0;i<args.length;i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
if(rs.next()){
T t = clazz.newInstance();
for (int i=0;i<columnCount;i++) {
Object columnValue = rs.getObject(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columnValue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(null,ps,rs);
}
return null;
}
8.6事務中必須知道的幾點
8.6.1 四大屬性(ACID)
-
原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。 -
一致性(Consistency)
事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。 -
隔離性(Isolation)
事務的隔離性是指一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。 -
永續性(Durability)
永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響。多餘的小知識:
BAT:百度、阿里、騰訊
BBA:賓士、寶馬、奧迪
TMD:頭條、美團、滴滴
8.6.2 資料操作過程中可能出現的問題(針對隔離性)
- 髒讀: 對於兩個事務 T1, T2, T1 讀取了已經被 T2 更新但還沒有被提交的欄位。之後, 若 T2 回滾, T1讀取的內容就是臨時且無效的。
- 不可重複讀: 對於兩個事務T1, T2, T1 讀取了一個欄位, 然後 T2 更新了該欄位。之後, T1再次讀取同一個欄位, 值就不同了。
- 幻讀: 對於兩個事務T1, T2, T1 從一個表中讀取了一個欄位, 然後 T2 在該表中插入了一些新的行。之後, 如果 T1 再次讀取同一個表, 就會多出幾行。
8.6.3 資料庫中的四種隔離級別
一致性和併發性:一致性越好,併發性越差。
-
Oracle 支援的 2 種事務隔離級別:READ COMMITED, SERIALIZABLE。 Oracle 預設的事務隔離級別為: READ COMMITED 。
-
Mysql 支援 4 種事務隔離級別。Mysql 預設的事務隔離級別為: REPEATABLE READ。
8.6.4 如何檢視並設定隔離級別
-
檢視當前的隔離級別:
SELECT @@tx_isolation;
-
設定當前 mySQL 連線的隔離級別:
set transaction isolation level read committed;
-
設定資料庫系統的全域性的隔離級別:
set global transaction isolation level read committed;