EJB容器上的CDI EntityManager注入VS @PersistenceContext实体管理器

时间:2019-01-21 22:52:31

标签: java jpa ejb cdi entitymanager

当我们在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一起使用,会产生相同的效果和性能吗? 预先感谢您的帮助

2 个答案:

答案 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,在该问题上可以找到很多精彩的讨论。