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

问题描述 投票:4回答:2

当我们在JAVA EE环境中的EntityManager上使用@PersistenceContext注释时,容器将创建entityManagerFactory(我猜测整个会话就是一个),并将为每个请求创建一个新的EntityManager(通过代理它)。

但是在没有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的这种方法,会产生相同的效果和性能吗?在此先感谢您的帮助

java jpa ejb cdi entitymanager
2个回答
2
投票

“使用CDI的那种方法会产生同样的效果”

不,它不会,使用@PersistenceContext,java EE容器将为每个事务提供不同的entityManager实例。

在这里,您将在每个注入点检索一个可能有问题的唯一实例(em不是线程安全的,而且如果您的数据在其他地方更新,因为相关实体已加载,则持久性上下文状态将与数据库不一致) 。


2
投票

不,效果不一样。就像Gab在之前的回答中所说,@PersistenceContext默认为每个事务注入一个单独的实体管理器。还有一个选项可以使用EXTENDED persistence context,但它超出了你的问题的范围。

使用您使用CDI提供的代码,您将获得每个注入点的实例,除非您为每个事务创建注入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,在那里您可以找到很多关于此事的精彩讨论。

© www.soinside.com 2019 - 2024. All rights reserved.