我正在使用 Java EE 7。我想知道将 JPAEntityManager注入应用程序范围的CDI bean 的正确方法是什么。您不能只使用@PersistanceContext注释注入它,因为EntityManager实例不是线程安全的。假设我们希望EntityManager在每个 HTTP 请求处理开始时创建并在处理 HTTP 请求后关闭。我想到了两个选择:
1. 创建一个请求范围的 CDI bean,它具有对 an 的引用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);
}
}
在这个例子中 anEntityManager将在创建时创建,并在销毁RequestScopedBean时关闭。RequestScopedBean现在我可以将注入移动到某个抽象类以将其从ApplicationScopedBean.
2. 创建一个产生 实例的生产者,EntityManager然后将该EntityManager实例注入应用程序范围的 CDI bean。
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 请求中创建一个 which,但是关闭呢EntityManager?处理完HTTP请求后也会关闭吗?我知道@PersistanceContext注释注入了 container-managed EntityManager。这意味着EntityManager当客户端 bean 被销毁时 an 将被关闭。在这种情况下,什么是客户端 bean?是 ,ApplicationScopedBean在应用程序停止之前永远不会被销毁,还是EntityManagerProducer? 有什么建议吗?
我知道我可以使用无状态 EJB 而不是应用程序范围的 bean,然后只EntityManager通过@PersistanceContext注释注入,但这不是重点:)