0

Spring のトランザクション サポートと JPA (Hibernate) を使用してエンティティを永続化しています。すべてが正常に機能していますが、1 つのリクエスト内で部分的な更新を処理するときに行き詰まりました。

ユーザー (HTTP) リクエストごとに、「メイン」ビジネス エンティティの更新が失敗した場合でも (たとえば、検証エラーが原因で)、ログ エントリをデータベース テーブルに書き込む必要があります。したがって、最初の/主要なトランザクションはロールバックされますが、2 番目 (ログの書き込み) はコミットする必要があります。これは、ログエントリを書き込むための正しい伝播レベルを使用して機能するようです:

@Repository
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class UserTracker extends ... {

  @PersistenceContext private EntityManager em;

  public void log(...) {
    // create log entity and persist it
    ...
    em.persist(log);
    em.flush();
  }

}

ただし、私の問題は、最初のトランザクションと同じ EntityManager が 2 番目のトランザクションに注入されることです。そのため、エンティティ マネージャーを (2 番目のトランザクションがコミットされたときに明示的または暗黙的に) フラッシュすると、最初のトランザクションからダーティ ビジネス エンティティもフラッシュされます。

どうすればこれを修正できますか? ロギング部分に2番目のクリーンで新鮮なEntityManagerを使用したいのですが、プログラムで開くことができることはわかっていますが、これを行うためのよりクリーンで宣言的な「Spring-way」はありますか?

編集:

私の問題は、2 番目のトランザクションがメインのビジネス トランザクション内にネストされていたという事実に起因する可能性があります。

|-------------- A --------------X   <- Rollback of main business transaction (A)
                    |--- B ---|     <- Commit of second log transaction (B)

2 つのトランザクションをシリアル化する問題を解決しました。

|--------- A --------X |--- B ---|

これですべてがうまくいきましたが、好奇心から: 提案されたように JDBC に頼らず、最初のアプローチに固執する場合: 2 番目の (ネストされた) トランザクションのエンティティ マネージャーをどのように構成して、新しいトランザクションを取得するか新しいトランザクション。これはできますか?

4

1 に答える 1

-1

報告している問題が発生している理由がわかりません。ロギングコードとビジネスロジックコードにREQUIRE_NEWがある場合、それらの間に干渉はないはずです。私のコードには非常によく似た設定があります。トランザクションは、あなたが思っている場所でトリガーされていますか?プロキシトランザクションまたはaspectJトランザクションを使用していますか?

プロキシトランザクションを使用している場合は、プロキシを通過してtxが開始することを保証するように注意する必要があります。

もう1つできることは、ユーザーロギングにSpringJDBCテンプレートを使用することです。@RepositoryにEntityManagerとJDBCTemplateの両方で処理を実行させ、同じメソッドでそれらを混在させないようにすることはまったく問題ありません。

于 2012-10-31T14:07:55.993 に答える