1

Springクラスを使用して1つのトランザクションを作成した以下のアクティビティを実行する以下のコードを記述しました。1行挿入しました。他のトランザクションを作成しました。別の行を挿入しました。コミットされた外部トランザクション。ロールバックされた内部トランザクション。

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
    jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(null);
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

両方の行がDBにコミットされていることを確認しました!! 出力は

trxstsOuter.isCompleted()true
trxstsInner.isCompleted()false
trxstsInner.isCompleted()true

それは正しい振る舞いですか?外部トランザクションのコミットを許可する前に、内部トランザクションを最初にコミット/ロールバックするべきではありませんか?外部トランザクションがコミットされた場合、内部のロールバックはエラーをスローする必要がありますか?

4

2 に答える 2

4

この例では、トランザクションPropagation.REQUIREDがデフォルト値として使用され、すべてのロジックトランザクションが単一の物理トランザクションにマップされています

伝播設定がPROPAGATION_REQUIREDの場合、設定が適用されるメソッドごとに論理トランザクションスコープが作成されます。このような各論理トランザクションスコープは、ロールバックのみのステータスを個別に決定でき、外部トランザクションスコープは内部トランザクションスコープから論理的に独立しています。もちろん、標準のPROPAGATION_REQUIRED動作の場合、これらのスコープはすべて同じ物理トランザクションにマップされます。したがって、内部トランザクションスコープに設定されたロールバックのみのマーカーは、外部トランザクションが実際にコミットする可能性に影響します(予想どおり)。

したがって、この例では、2つの論理トランザクションが1つの物理トランザクションにマップされています。

ドキュメントを参照してください

于 2012-12-09T11:41:37.847 に答える
2

現在のコードでは、2番目のgetTransaction呼び出しはnoopです。この動作は、PropagationBehaviorと呼ばれる属性によって制御されます。デフォルトの伝播動作はPROPAGATION_REQUIREDです。これは、存在しない場合は新しいトランザクションを開始するか、既存のトランザクションに参加することを意味します。あなたの場合、これが起こっていることです。

2番目のトランザクションの伝播動作属性をPROPAGATION_REQUIRES_NEWに変更すると、期待どおりの動作が得られます。内部トランザクションがコミット/ロールバックされると、外部トランザクションは一時停止され、新しいトランザクションが作成されます。外部トランザクションは自動的に再開されます。この動作を組み込むようにコードを変更しました。内部トランザクションの前に外部トランザクションをコミットしようとすると、例外が発生するはずです。シーケンスを修正すると、コミットは独立して行われます。

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    // start a new transaction.
    DefaultTransactionDefinition nestedTransDef = new DefaultTransactionDefinition();
    nestedTransDef.setPropagationBehavior(             
           TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(nestedTransDef);
     System.out.println("trxstsInner.isNewTransaction()"+ trxstsInner.isNewTransaction());  
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
    System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
    dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

余談ですが、トランザクションを管理するためにアノテーションを使用する必要があります。これは、コードにトランザクションを組み込むためのはるかにクリーンで優れた方法です。プログラマティックトランザクションは、より詳細な制御が必要なまれなケースのみを対象としています。また、TransactionTemplateを使用してプログラムによるトランザクションを実行することをお勧めします。

于 2012-12-09T12:17:08.483 に答える