JDBC 事務處理【最終版】

TZQ_DO_Dreamer發表於2014-09-07
事務:一組邏輯操作單元,使資料從一種狀態變換到另一種狀態。
事務處理(事務操作):保證所有事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。
當在一個事務中執行多個操作時,要麼所有的事務都被提交(commit),那麼這些修改就永久地儲存下來;要麼資料庫管理系統將放棄所作的所有修改,整個事務回滾(rollback)到最初狀態。
為確保資料庫中資料的一致性,資料的操縱應當是離散的成組的邏輯單元:當它全部完成時,資料的一致性可以保持,而當這個單元中的一部分操作失敗,整個事務應全部視為錯誤,所有從起始點以後的操作應全部回退到開始狀態。 

當一個連線物件被建立時,預設情況下是自動提交事務:每次執行一個 SQL 語句時,如果執行成功,就會向資料庫自動提交,而不能回滾

JDBC 事務處理
    為了讓多個 SQL 語句作為一個事務執行:
  • 呼叫 Connection 物件的 setAutoCommit(false); 以取消自動提交事務
  • 在所有的 SQL 語句都成功執行後,呼叫 commit(); 方法提交事務
  • 在出現異常時,呼叫 rollback(); 方法回滾事務
  • 若此時 Connection 沒有被關閉, 則需要恢復其自動提交狀態

// AA 使用者轉給 BB 使用者 100元。 1.AA 使用者 扣除 100 2.BB使用者增加 100
@Test
     public void testUpdate2 () {
        Connection conn = null ;
         try {
            conn = JDBCUtils .getConnection ();
             // 1. 開啟事務
            conn .setAutoCommit ( false);
            String sql1 = "update user_table set balance = balance - ? where user = ?";
            updateWithTx (conn , sql1 , 100 , "AA");

             // 模擬網路異常
             // System.out.println(10 / 0);

            String sql2 = "update user_table set balance = balance + ? where user = ?";
            updateWithTx (conn , sql2 , 100 , "BB");
             // 2. 提交事務
            conn .commit ();
         } catch (Exception e ) {
            e .printStackTrace ();
             if (conn != null ) {
                 try {
                     // 3. 回滾事務
                    conn .rollback (); //出現異常則直接會執行 catch 中的內容,然後使之前對資料庫的操作回滾
                 } catch (SQLException e1 ) {
                    e1 .printStackTrace ();
                 }
             }
         } finally {
            JDBCUtils .close ( null, null, conn);
         }
     }

     // 通用的增刪改方法( version 3.0 : 考慮上資料庫事務
     public void updateWithTx (Connection conn , String sql , Object... args) {

         // 1. 返回一個PreparedStatement 的物件,涉及預編譯 sql 語句
        PreparedStatement ps = null ;
         try {
            ps = conn .prepareStatement (sql );
             // 2. 填充佔位符
             for ( int i = 0; < args .length ; i ++) {
                ps .setObject (+ 1 , args [i ]);// 設定佔位符
             }
             // 3. 執行
            ps .executeUpdate ();
         } catch (Exception e ) {
            e .printStackTrace ();
         } finally {
             // 4. 關閉操作
            JDBCUtils .close ( null, ps , null); // 注意連線不能關,否則會有語句執行不到
         }
     }


相關文章