我正在使用 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
注释注入,但这不是重点:)