当我们在JAVA EE环境中在EntityManager上使用@PersistenceContext批注时,容器将创建EntityManagerFactory(我猜为整个会话一个),并为每个请求创建一个新的EntityManager(通过代理)。 / p>
但是在没有JAVA EE容器的情况下使用CDI时,我看到的是这样的话:
public class EntityManagerProducer {
private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("livraria");
@Produces
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void close(EntityManager em) {
em.close();
}
}
将这种方法与CDI一起使用,会产生相同的效果和性能吗? 预先感谢您的帮助
答案 0 :(得分:2)
“将这种方法与CDI一起使用将具有相同的效果”
不会,使用@PersistenceContext
的Java EE容器将为每个事务提供一个不同的entityManager实例。
在这里,您将在每个注入点检索一个唯一的实例,这可能会出现问题(它们不是线程安全的,此外,如果您的数据在其他地方更新,则持久性上下文状态将与数据库不一致,因为相关实体具有已加载)。
答案 1 :(得分:2)
不,效果不一样。就像Gab在先前的回答中所说的那样,@PersistenceContext
默认情况下会为每个事务注入一个单独的实体管理器。还有一个使用EXTENDED persistence context的选项,但这超出了您的问题范围。
使用CDI提供的代码,您将为每个注入点获得一个实例,除非您为每个事务创建 injecting bean(很可能不是),否则它是不一样的。
但是,您可以做的是为实体管理器使用RequestScoped生产器,如下所示:
public class EntityManagerProducer {
private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("livraria");
@Produces
@RequestScoped
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
}
这将为您提供Web应用程序中的类似语义,但是如果您计划混合EJB和非EJB代码,则可能会有一些陷阱,因为该实体管理器不知道正在进行的事务。 here涵盖了其中一些内容。
您还应该检查类似的问题Getting a reference to EntityManager in Java EE applications using CDI,在该问题上可以找到很多精彩的讨论。