web-dev-qa-db-ja.com

@ApplicationScoped CDI Beanと@ PersistenceContext-これは安全ですか?

CDIでこのようなことをするのは安全ですか?

@Named
@ApplicationScoped
public class DAO {

   @PersistenceContext
   private EntityManager entityManager;

}

EntityManager自体はスレッドセーフではないため、@ApplicationScopedのような共有グローバルコンテキストでは使用しないでください。ただし、@PersistenceContextで挿入されたオブジェクトは、実際には基になるEntityManagerのスレッド対応ラッパーであるため、これで問題ありませんか?

この件に関する他の投稿を見たことがありますが、この特定のケースに対する信頼できる答えを見つけることができませんでした。例えば:

Java CDI @PersistenceContextとスレッドセーフ

たとえば、@Statelessと一緒に使用しても安全なようですが、それが@Statelessの動作方法によるものなのか、それとも@PersistenceContext自体に固有の何かによるものなのかはわかりません。

[〜#〜] edit [〜#〜]私の混乱の原因は、@PersistenceContextEntityManagerラッパーを注入したことです進行中のトランザクションがすでにあるかどうかを把握するために、現在のスレッドを認識しているようです。したがって、おそらく私はスレッド認識とスレッドセーフを混同していて、それらは2つの異なるものです。

27
wrschneider

この場合、CDIはエンティティマネージャのコンテキストプロキシを作成しないと確信しています。結局のところ、それはどのような範囲にあるのでしょうか?架空の_@ThreadScoped_または単に_@RequestScoped_に似たものが必要な場合がありますが、_@PersistenceContext_はCDI注釈ではなく、CDIはそのセマンティクスを変更しません。

つまり、ここで起こっているのはJava EE 6プラットフォームの「マネージドBean」インジェクションです。これは、サーブレットにエンティティマネージャをインジェクションするのと似ています。どちらの場合も、スレッドセーフではないインスタンスが提供されます。直接使用します。

たとえば、@ Statelessで使用しても安全なようですが、それが@Statelessの動作方法によるものなのか、@ PersistenceContext自体に固有の何かによるものなのかはわかりません。

これは、_@Stateless_の動作方法によるものです。ステートレスBeanのメソッドへのすべてのリクエスト(呼び出し)は、コンテナによって一意のインスタンスにルーティングされます。コンテナは、同じBeanで2つのスレッドがアクティブにならないことを保証します。

CDIを使用すると、エンティティマネージャーをリクエストスコープのBeanにカプセル化し、それをアプリケーションスコープのBeanに注入することで、リクエストごとに同様の効果を得ることができます。

_import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@RequestScoped
public class EntityManagerProvider {

    @PersistenceContext
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }

}
_

以前にエンティティマネージャを注入したBeanにこれを注入します。

_@Named
@ApplicationScoped
public class DAO {

   @Inject
   private EntityManagerProvider entityManagerProvider;

}
_

これにより、リクエストごとに一意のエンティティマネージャーが提供されます。これもプロデューサーメソッドに簡単に変換できるため、注入されたプロバイダーでgetEntityManager()を呼び出す必要はありません。

24
Arjan Tijms