1. 程式人生 > 其它 >JDBC複習--資料庫事務

JDBC複習--資料庫事務

技術標籤:JDBC學習

此部落格僅為本人學習JDBC時所做記錄。

08-資料庫事務

8.1 事務

一組邏輯操作單元,使資料從一種狀態變換到另一種狀態。

一組邏輯操作單元,一個或多個DML操作

8.2 事務處理的原則

保證所有事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。

當在一個事務中執行多個操作時,要麼所有的事務都被提交(commit),那麼這些修改就永久地儲存下來;要麼資料庫管理系統將放棄所作的所有修改,整個事務回滾(rollback)到最初狀態

說明:

  1. 資料一旦提交,就不回滾

  2. 哪些操作會導致資料的自動提交

    • 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)
  1. 原子性(Atomicity)
    原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。

  2. 一致性(Consistency)
    事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。

  3. 隔離性(Isolation)
    事務的隔離性是指一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。

  4. 永續性(Durability)
    永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響。

    多餘的小知識:

    BAT:百度、阿里、騰訊

    BBA:賓士、寶馬、奧迪

    TMD:頭條、美團、滴滴

8.6.2 資料操作過程中可能出現的問題(針對隔離性)
  1. 髒讀: 對於兩個事務 T1, T2, T1 讀取了已經被 T2 更新但還沒有被提交的欄位。之後, 若 T2 回滾, T1讀取的內容就是臨時且無效的。
  2. 不可重複讀: 對於兩個事務T1, T2, T1 讀取了一個欄位, 然後 T2 更新了該欄位。之後, T1再次讀取同一個欄位, 值就不同了。
  3. 幻讀: 對於兩個事務T1, T2, T1 從一個表中讀取了一個欄位, 然後 T2 在該表中插入了一些新的行。之後, 如果 T1 再次讀取同一個表, 就會多出幾行。
8.6.3 資料庫中的四種隔離級別

一致性和併發性:一致性越好,併發性越差。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-LpOyGIbA-1608480337350)(file://C:\Users\蔲丫丫\Desktop\尚矽谷_宋紅康_JDBC核心技術(2019新版)]\1-課件\課件-md\尚矽谷_宋紅康_JDBC.assets\1555586275271.png?lastModify=1608457562)

  • Oracle 支援的 2 種事務隔離級別:READ COMMITED, SERIALIZABLE。 Oracle 預設的事務隔離級別為: READ COMMITED

  • Mysql 支援 4 種事務隔離級別。Mysql 預設的事務隔離級別為: REPEATABLE READ。

8.6.4 如何檢視並設定隔離級別
  1. 檢視當前的隔離級別:

    SELECT @@tx_isolation;
    
  2. 設定當前 mySQL 連線的隔離級別:

    set  transaction isolation level read committed;
    
  3. 設定資料庫系統的全域性的隔離級別:

    set global transaction isolation level read committed;