[セットトップ]Java JDBCトランザクションメカニズム


Java JDBCトランザクションメカニズム
まず、既存のJDBC操作が私たちにどんな重大な問題をかけてくるかを見てみましょう.例えば、ビジネスがあります.私たちが情報を修正してからこの情報を調べてみると、これは簡単なビジネスであり、実現も非常に簡単ですが、このビジネスがマルチスレッドの高いプラットフォームの下に置かれると、問題は自然に発生します.例えば、修正を実行した後、クエリーを実行する前に、スレッドが修正文を実行しました.これは私たちがクエリーを実行することです.見た情報は私たちが修正したものとは異なる可能性があります.この問題を解決するために、JDBCトランザクションメカニズムを導入しなければなりません.実際にはコードの実現は簡単です.原理の実現例を示して参考にしてください.
private Connection conn = null;  
private PreparedStatement ps = null;  
 
try {  
    conn.setAutoCommit(false);  //        false  
              
    ps.executeUpdate("  SQL"); //        
    ps.executeQuery("  SQL");  //                       
    conn.commit();      //              
              
} catch (Exception e) {  
    conn.rollback();    //              ,           
    e.printStackTrace();  
} 

事務に関する理論1.トランザクション(Transaction)の4つのプロパティ(ACID)原子間(Atomic)によるデータの変更は、すべて実行されるか、すべて実行されないかのいずれかです.コンシステンシ(Consistent)トランザクションの実行前後において、データの状態は一貫性を維持します.独立性(Isolate)あるトランザクションの処理は、別のトランザクションの処理に影響を与えることはできません.Durableトランザクションが終了し、その効果はデータベース内で永続化されます.
2.トランザクションの同時処理によって発生する可能性のある問題ダーティリード(dirty read)あるトランザクションは、別のトランザクションがコミットされていないデータを読み取り、1つのトランザクションを繰り返して読み取ることができない操作により、別のトランザクションが異なるデータ幻リード(phantom read)あるトランザクションに前後2回読み込む操作により、別のトランザクションの前後2回のクエリの結果データ量が異なる.例:トランザクションA、Bが同時に実行されると、Aトランザクションupdate後、BトランザクションselectはAがコミットしていないデータを読み出し、Aトランザクションrollbackの場合、Bが読み出したデータは無効な「汚い」データである.Bトランザクションselectがデータを読み込むと、Aトランザクションupdate操作でBトランザクションselectからのデータが変更されます.このとき、Bトランザクションは再びデータを読み、前後2回のデータが異なることがわかります.Bトランザクションselectがデータを読み込むと、AトランザクションinsertまたはdeleteがAトランザクションのselect条件を満たすレコードを作成します.このとき、Bトランザクションは再びselectを実行し、前回存在しなかったレコード(「幻」)または前回のレコードがなくなったことを検出します.
JDBCのトランザクションサポートJDBCのトランザクションサポートは、(1)オートコミットモード(Auto-commit mode)Connectionがトランザクションがいつ終了するかを指定するauto-commitのプロパティを提供する3つの側面に現れます.a.auto-commitがtrueの場合、独立したSQL操作の実行が完了すると、トランザクションはすぐに自動的にコミットされます.つまり、各SQL操作はトランザクションです.独立したSQL操作がいつ実行されるかは、JDBC仕様では、insert、update、deleteなどのデータ操作言語とcreate、dropなどのデータ定義言語に対して、文が実行されると実行完了とみなされます.select文の場合、関連付けられたResultSetオブジェクトが閉じている場合は、実行済みとみなされます.ストアド・プロシージャまたは他の複数の結果を返す文について、それに関連付けられたすべてのResultSetオブジェクトがすべて閉じられた場合、すべてのupdate count(update、deleteなどの文の操作が影響する行数)とoutput parameter(ストアド・プロシージャの出力パラメータ)が取得された後、実行済みとみなされます.b.auto-commitがfalseの場合、各トランザクションは呼び出しcommitメソッドを表示してコミットするか、rollbackメソッドを呼び出してロールバックする必要があります.Auto-commitのデフォルトはtrueです.
デフォルトのJDBCトランザクションは自動コミットされるため、データベース接続を取得した後、接続を非自動コミットモードに変更する必要があります.
public void updateCoffeeSales(HashMap<String, Integer> salesForWeek)
    throws SQLException {

    PreparedStatement updateSales = null;
    PreparedStatement updateTotal = null;

    String updateString =
        "update " + dbName + ".COFFEES " +
        "set SALES = ? where COF_NAME = ?";

    String updateStatement =
        "update " + dbName + ".COFFEES " +
        "set TOTAL = TOTAL + ? " +
        "where COF_NAME = ?";

    try {
        con.setAutoCommit(false);
        updateSales = con.prepareStatement(updateString);
        updateTotal = con.prepareStatement(updateStatement);

        for (Map.Entry<String, Integer> e : salesForWeek.entrySet()) {
            updateSales.setInt(1, e.getValue().intValue());
            updateSales.setString(2, e.getKey());
            updateSales.executeUpdate();
            updateTotal.setInt(1, e.getValue().intValue());
            updateTotal.setString(2, e.getKey());
            updateTotal.executeUpdate();
            con.commit();
        }
    } catch (SQLException e ) {
        JDBCTutorialUtilities.printSQLException(e);
        if (con != null) {
            try {
                System.err.print("Transaction is being rolled back");
                con.rollback();
            } catch(SQLException excep) {
                JDBCTutorialUtilities.printSQLException(excep);
            }
        }
    } finally {
        if (updateSales != null) {
            updateSales.close();
        }
        if (updateTotal != null) {
            updateTotal.close();
        }
        con.setAutoCommit(true);
    }
}

JDBCは5つの異なるトランザクション独立性レベルを提供し、Connectionで定義されています.
(2)トランザクション独立性レベル(Transaction Isolation Levels)JDBCは5種類のトランザクション独立性レベルを定義しています:TRANSACTION_NONE JDBCドライバはトランザクションTRANSACTIONをサポートしていません.READ_UNCOMMITTEDでは、汚れた読み取り、重複しない読み取り、幻の読み取りが許可されます.TRANSACTION_READ_COMMITTEDは汚い読みは禁止されていますが、繰り返し読みや幻読みは禁止されています.TRANSACTION_REPEATABLE_READは汚れた読みと繰り返してはいけないことを禁止し、単に幻読みを実行する.TRANSACTION_SERIALIZABLEは、汚れた読み取り、重複しない読み取り、幻の読み取りを禁止します.
Isolation Level
Transactions
Dirty Reads
Non-Repeatable Reads
Phantom Reads TRANSACTION_NONE
Not supported
Not applicable
Not applicable
Not applicable TRANSACTION_READ_COMMITTED
Supported
Prevented
Allowed
Allowed TRANSACTION_READ_UNCOMMITTED
Supported
Allowed
Allowed
Allowed TRANSACTION_REPEATABLE_READ
Supported
Prevented
Prevented
Allowed TRANSACTION_SERIALIZABLE
Supported
Prevented
Prevented
Prevented
OracleはTRANSACTIONをサポートしています.READ_UNCOMMITTEDとTRANSACTION_SERIALIZABLE、デフォルトはTRANSACTION_READ_UNCOMMITTED.
接続の独立性レベルを制御するには、次の方法を使用します.
conn.setTransactionIsolation(Connection.TRANSACTION_XXX);
(3)セーブポイント(SavePoint)
JDBCはSavePointインタフェースを定義し、より細かいパーティクルでのトランザクション制御メカニズムを提供します.セーブポイントが設定されている場合は、ロールバックトランザクション全体ではなく、ロールバックをそのセーブポイントの状態にすることができます.ConnectionインタフェースのsetSavepointメソッドとreleaseSavepointメソッドでは、セーブポイントを設定および解放できます.
JDBC 3.0の新機能では、トランザクションcommitとrollbackのより良いサポートが提供され、トランザクション中に2つのオペレーションの間に名前付きのストレージポイントをタグとして挿入できるため、トランザクションをそのタグにロールバックし、タグが有効になる前のすべてのオペレーションを保持できます.
例:
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
 
stmt.executeUpdate(update1);
Savepoint point1 = conn.setSavepoint("point1");
 
stmt.executeUpdate(update2);
stmt.executeUpdate(update3);
 
conn.rollback(point1);
conn.commit();

JDBC仕様では、トランザクションの上記のサポート動作が定義されていますが、データベース・ベンダーごとにトランザクションのサポートの程度が異なる場合があります.プログラム内で任意に設定すると、目的の効果が得られない場合があります.このため、JDBCはDatabaseMetaDataインタフェースを提供し、一連のJDBC特性サポート状況の取得方法を提供している.例えば、DatabaseMetaData.S u p p p o r t s T r o n s a c t ionIsolationLevelメソッドは、トランザクションの独立性レベルのサポート状況を判断する、DatabaseMetaData.supportsSavepointsメソッドは,セーブポイントのサポート状況を判断できる.
参照先:
【1】JavaのJDBCトランザクションの詳細http://blog.csdn.net/chenyongsuda/article/details/5641412
【2】JDBC-トランザクションhttp://blog.csdn.net/oswin_jiang/article/details/3275370
【3】Using Transactions http://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html