13

次のコードは、エンティティを永続化するたびに実行されます。物事はうまくいっているようですが、それがどのように機能するのか理解できません!

EntityManager em = getEntityManager();
EntityTransaction userTransaction = em.getTransaction();
userTransaction.begin();
em.persist( ent );
userTransaction.commit();

上記の EntityManager は、アプリケーション全体で共有される単一のインスタンスです。取引開始後 私は em.persist(entity). とだけ言っています。どのトランザクションに属しているかを休止状態はどのように認識しますか!

アプリケーションに 10 人の同時ユーザーがいて、10 個のスレッドすべてが上記のコードを実行しているとします。したがって、10 個の独立したトランザクションが作成され、コミットされます。ただし、10 の異なるエンティティすべてをそれぞれのトランザクションに関連付けているわけではありません。では、JPAはどのようにそれを解決できますか!

回答に基づく; 以下があります。スレッドごとに EntityManager インスタンスが必要だと言っているのですか? それはサーバー上での殺害ではありませんか! これらのインスタンスをプールする必要がありますか? ある種の Connection Pooling を再度実装するのと同じではないでしょうか?

4

4 に答える 4

7

トランザクションにThreadLocal変数を使用しています。

UserTransactionのドキュメントも参照してください。

begin()
新しいトランザクションを作成し、それを現在のスレッドに関連付けます。

ただし、スレッドセーフであることが保証されていないため、EntityManager を共有しないでください。

ただし、EJB に注入する場合は、スレッドセーフについて心配する必要はありません: http://www.adam-bien.com/roller/abien/entry/is_in_an_ejb_injected

Spring を使用して注入している場合は、スレッドセーフなプロキシを取得します: http://static.springsource.org/spring/docs/3.1.1.RELEASE/spring-framework-reference/html/orm.html #orm-jpa-straight

EntityManagerFactory インスタンスはスレッドセーフですが、EntityManager インスタンスはそうではありません。注入された JPA EntityManager は、JPA 仕様で定義されているように、アプリケーション サーバーの JNDI 環境からフェッチされた EntityManager のように動作します。現在のトランザクション EntityManager がある場合は、すべての呼び出しを委任します。それ以外の場合は、操作ごとに新しく作成された EntityManager にフォールバックし、事実上、その使用がスレッドセーフになります。

于 2012-06-27T08:16:05.133 に答える
6

あなたは十分に幸運なので、それはうまくいきます。幸運なことに、commit と begin が正しい順序で呼び出されます (誤って)。

複数のスレッドからエンティティ マネージャーの単一のインスタンスを使用します。スレッドセーフであることが保証されていないため、これは間違ったことです。EntityTransaction を介したリソース レベル トランザクションへのアクセスは、スレッドではなくエンティティ マネージャー インスタンスにバインドされます。

その結果、同じ EntityTransaction を共有し、幸運にも複数のトランザクションで連続して使用しています。複数のトランザクションを開始および終了するためにシリアルに使用することは問題ありませんが、多くのスレッドから使​​用することはできません。

hibernate (4.1.4) では、参照は AbstractEntityManageImpl クラスの tx インスタンス フィールドに格納されますが、それは単なる実装の詳細です。

于 2012-06-27T08:13:37.557 に答える
2

トランザクションは、ThreadLocal 変数を使用して、何らかの方法で現在のスレッドに関連付けられます。

于 2012-06-27T07:16:19.070 に答える
0

Hibernate に関係なくJTAがどのように機能するかを理解することをお勧めします。理解することは非常に重要です。
さらに、コンテナ管理のトランザクションと Bean 管理のトランザクションについて読んでください。
コンテナ管理のトランザクションで作業している場合、Bean に対して EntityManager を注入するトランザクション スコープを指定できます。
たとえば、スコープが REQUIRED の場合、別の Bean がこの Bean を呼び出す場合、トランザクションのコンテキストではなく、新しいトランザクションが開かれます。トランザクションがすでに存在する場合は、同じトランザクションを使用します。トランザクションはシステム内の高価なリソースであるため、これを理解することが重要です。

トランザクション オブジェクトは ThreadLocal に関連付けられていますが、TransactionManager の実装に応じて、別のスレッドが中断されたトランザクションを再開する場合があります (私はJBossTransactionManagerについて話しています) 。

于 2012-06-27T07:48:24.527 に答える