我可以使用CDI和@PersistenceContext注入JPA EntityManager,就像Spring一样吗?

时间:2016-11-07 15:46:34

标签: spring jpa java-ee weld

在Spring,我可以注入一个javax.persistence.EntityManager 使用注释@javax.persistence.PersistenceContext进入Spring bean,如下所示:

@Service
public class MyRepository {
    @PersistenceContext
    private EntityManager entityManager;
}

这在第20.5.2 Implementing DAOs based on plain JPA章的Spring文档中有记录。

如果我没有使用Java EE容器,有没有办法使用CDI(特别是Weld)?

特别是,是否可以为CDI重用注释@PersistenceContext(因为现有代码在Spring中使用它)?

据我了解:当使用Java EE容器时,容器将解释注释并注入EntityManager。那是对的吗?有没有办法让这个工作使用Weld,但没有Java EE容器?

我尝试使用Weld(在Tomcat中,没有Java EE)将上面的类注入到另一个类中。注入发生,因此Weld正确创建MyRepository的实例,但字段MyRepository.entityManagernull,就像注释@PersistenceContext被忽略一样。

这里发生了什么(或者更确切地说,没有发生)?

2 个答案:

答案 0 :(得分:4)

你可以这样做: 创建 Entity Manager Factory Producer

EntityNo int
City nvarchar(MAX)
Province nvarchar(MAX)
EntityDate datetime

并创建 Entity Manager Producer

public class EntityManagerFactoryProducer {

    @Produces
    @ApplicationScoped
    public EntityManagerFactory create() {
        return Persistence.createEntityManagerFactory("PU");
    }

    public void destroy(@Disposes EntityManagerFactory factory) {
        factory.close();
    }

}

然后你可以使用依赖注入(CDI将为每个请求创建一个em)

public class EntityManagerProducer {

    @Inject
    transient EntityManagerFactory emf;

    @Produces
    @RequestScoped
    public EntityManager create() {
        return emf.createEntityManager();
    }

    public void destroy(@Disposes EntityManager em) {
        em.close();
    }
}

您必须在主方法

中启动CDI上下文
@Inject
EntityManager entityManager;

PS。如果你有多个PU使用@Qualifier

答案 1 :(得分:3)

虽然MilkMaid的答案是一个合理的方法,但我只想添加一些幕后提示。

  

如果我没有使用Java EE容器,有没有办法使用CDI(特别是Weld)?

简短回答 - 有。焊接可以允许注射您希望注射的任何对象旁边,但是您需要注意谁拥有/管理此对象。在你的情况下,它是来自JPA的EntityManager,所以猜猜 - JPA管理这种对象的生命周期。因此,您需要为此类对象创建一个“包装器”(实际上是它的代理),该对象将由CDI / Weld处理。那就是你需要的制作人

  

好像注释@PersistenceContext被忽略了。

确实,它被忽略了。这是发生的事情的简化。通常情况下,在EE容器中,Weld会使注入发生,但其背后的真正魔力不是Weld核心代码,而是EE服务器端的集成(谁采用Weld SPI来处理这样的注释并将它们转换为bean它然后注入)。

一般来说,尝试处理EE容器之外的“EE内容”可能会变得棘手,因为您遇到了最初发生在容器内部的大量集成,但您现在需要自己处理它。

从技术上讲,可以通过编写CDI extension来使@PersistenceContext注释工作正常。然而,这是一个讨厌的黑客而不是其他任何东西 - 人们会弯曲仅限EE的注释用于SE使用。我会建议不要这样做,但是如果你仍然想要这样做,那么想法就是基本上让CDI认为@PersistanceContext是另一个@Inject plus提供给制作人。这意味着很多手动工作,CDI中没有内置机制来处理这个问题 - 这通常是EE服务器的责任。