27

Java EE 7 を使用しています。アプリケーション スコープのCDI Beanに JPAEntityManagerを挿入する適切な方法を知りたいです。インスタンスはスレッドセーフではないため、アノテーションを使用して注入することはできません。すべての HTTP リクエスト処理の開始時に作成され、HTTP リクエストが処理された後に閉じられると仮定しましょう。2つのオプションが頭に浮かびます:@PersistanceContextEntityManagerEntityManager

1. への参照を持つ要求スコープの CDI Bean を作成し、EntityManagerその Bean をアプリケーション スコープの CDI Bean に注入します。

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

@RequestScoped
public class RequestScopedBean {

    @PersistenceContext
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }
}

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

@ApplicationScoped
public class ApplicationScopedBean {

    @Inject
    private RequestScopedBean requestScopedBean;

    public void persistEntity(Object entity) {
        requestScopedBean.getEntityManager().persist(entity);
    }
}

この例でEntityManagerは、 が作成されると が作成され、が破棄さRequestScopedBeanれると が閉じられます。RequestScopedBeanこれで、インジェクションを抽象クラスに移動して、ApplicationScopedBean.

2. のインスタンスを生成するプロデューサを作成し、そのインスタンスをアプリケーション スコープの CDI Bean にEntityManager注入します。EntityManager

import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class EntityManagerProducer {

    @PersistenceContext
    @Produces
    @RequestScoped
    private EntityManager entityManager;
}

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;

@ApplicationScoped
public class ApplicationScopedBean {

    @Inject
    private EntityManager entityManager;

    public void persistEntity(Object entity) {
        entityManager.persist(entity);
    }
}

この例ではEntityManager、HTTP リクエストごとに作成される もありますが、 ?を閉じるのはどうでしょうか。EntityManagerHTTP リクエストが処理された後も閉じられますか? @PersistanceContextアノテーションが container-managed を注入することは知っていEntityManagerます。これはEntityManager、クライアント Bean が破棄されると が閉じられることを意味します。この状況でのクライアント Bean とは何ですか? ApplicationScopedBeanアプリケーションが停止するまで決して破棄されない ですか、それともEntityManagerProducerですか? 何かアドバイスはありますか?

アプリケーション スコープ Bean の代わりにステートレス EJB を使用して、EntityManagerアノテーション@PersistanceContextで注入できることはわかっていますが、それは重要ではありません :)

4

4 に答える 4

0

以下の例のように、@Dispose注釈を使用して を閉じる必要があります。EntityManager

@ApplicationScoped
public class Resources {

    @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;

    @Produces
    @Default
    @RequestScoped
    public EntityManager create() {
        return this.entityManagerFactory.createEntityManager();
    }

    public void dispose(@Disposes @Default EntityManager entityManager) {
        if (entityManager.isOpen()) {
            entityManager.close();
        }
    }

}
于 2014-07-19T19:46:23.157 に答える