我可以使用 CDI 和 @PersistenceContext 注入 JPA EntityManager,就像 Spring 一样吗?
Can I inject an JPA EntityManager using CDI and @PersistenceContext, like with Spring?
在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(特别是焊接)来做到这一点?
特别是,是否可以为 CDI 重用注释 @PersistenceContext
(因为现有代码将其与 Spring 一起使用)?
据我了解:当使用 Java EE 容器时,容器将解释注释并注入一个 EntityManager。那是对的吗?有没有办法在没有 Java EE 容器的情况下使用 Weld 使其工作?
我尝试使用 Weld(在 Tomcat 中,没有 Java EE)将上面的 class 注入另一个 class。发生注入,因此 Weld 正确地创建了 MyRepository
的实例,但是字段 MyRepository.entityManager
是 null
,就好像注释 @PersistenceContext
被忽略了一样。
这里发生了什么(或者更确切地说,没有发生)?
你可以这样做:
创建 实体管理器工厂生产者
public class EntityManagerFactoryProducer {
@Produces
@ApplicationScoped
public EntityManagerFactory create() {
return Persistence.createEntityManagerFactory("PU");
}
public void destroy(@Disposes EntityManagerFactory factory) {
factory.close();
}
}
并创建 Entity Manager Producer
public class EntityManagerProducer {
@Inject
transient EntityManagerFactory emf;
@Produces
@RequestScoped
public EntityManager create() {
return emf.createEntityManager();
}
public void destroy(@Disposes EntityManager em) {
em.close();
}
}
然后你可以使用依赖注入(CDI会为每个请求创建一个em)
@Inject
EntityManager entityManager;
您必须在主方法中启动 CDI 上下文
public static void main(String[] args) throws IOException {
Weld weld = new Weld();
WeldContainer container = weld.initialize();
Application application = container.instance().select(Application.class).get();
application.run();
weld.shutdown();
}
ps。如果你有不止一个 PU 使用 @Qualifier
虽然 MilkMaid 的回答是一个不错的选择,但我只想添加一些幕后提示。
Is there a way to do this using CDI (specifically, Weld) if I am not using a Java EE container?
简答 - 有。 Weld 可以允许在您希望可注入的任何对象旁边注入,但是您需要注意 who owns/manages 这个对象。在你的例子中,它是 EntityManager
这是来自 JPA 的东西,所以猜猜是什么 - JPA 管理此类对象的生命周期。因此,您需要为将由 CDI/Weld 处理的此类对象创建一个 "wrapper"(实际上它是一个代理)。这就是你需要 producer 的原因。
as if the annotation @PersistenceContext was ignored.
确实被忽略了。这是对所发生情况的简化。通常,在 EE 容器中,Weld 会使注入发生,但背后真正的魔力不是 Weld 核心代码,而是 EE 服务器端的集成(谁采用 Weld SPI 来处理此类注释并将它们转换为 bean然后注入)。
一般来说,尝试在 EE 容器之外处理 'EE stuff' 可能会很棘手,因为您会遇到很多最初发生在容器内部的集成,但现在您需要自己处理。
从技术上讲,可能可以使 @PersistenceContext
注释起作用,也许可以通过编写 CDI extension。然而,这是一个令人讨厌的 hack,而不是其他任何东西 - 人们会为了 SE 使用而弯曲 EE-only 注释。我会反对它,但如果你仍然想那样做,这个想法基本上是让 CDI 认为 @PersistanceContext 是另一个 @Inject 加上提供生产者。这将意味着大量的手动工作,CDI 中没有内置机制来为您处理 - 这通常是 EE 服务器的责任。
在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(特别是焊接)来做到这一点?
特别是,是否可以为 CDI 重用注释 @PersistenceContext
(因为现有代码将其与 Spring 一起使用)?
据我了解:当使用 Java EE 容器时,容器将解释注释并注入一个 EntityManager。那是对的吗?有没有办法在没有 Java EE 容器的情况下使用 Weld 使其工作?
我尝试使用 Weld(在 Tomcat 中,没有 Java EE)将上面的 class 注入另一个 class。发生注入,因此 Weld 正确地创建了 MyRepository
的实例,但是字段 MyRepository.entityManager
是 null
,就好像注释 @PersistenceContext
被忽略了一样。
这里发生了什么(或者更确切地说,没有发生)?
你可以这样做: 创建 实体管理器工厂生产者
public class EntityManagerFactoryProducer {
@Produces
@ApplicationScoped
public EntityManagerFactory create() {
return Persistence.createEntityManagerFactory("PU");
}
public void destroy(@Disposes EntityManagerFactory factory) {
factory.close();
}
}
并创建 Entity Manager Producer
public class EntityManagerProducer {
@Inject
transient EntityManagerFactory emf;
@Produces
@RequestScoped
public EntityManager create() {
return emf.createEntityManager();
}
public void destroy(@Disposes EntityManager em) {
em.close();
}
}
然后你可以使用依赖注入(CDI会为每个请求创建一个em)
@Inject
EntityManager entityManager;
您必须在主方法中启动 CDI 上下文
public static void main(String[] args) throws IOException {
Weld weld = new Weld();
WeldContainer container = weld.initialize();
Application application = container.instance().select(Application.class).get();
application.run();
weld.shutdown();
}
ps。如果你有不止一个 PU 使用 @Qualifier
虽然 MilkMaid 的回答是一个不错的选择,但我只想添加一些幕后提示。
Is there a way to do this using CDI (specifically, Weld) if I am not using a Java EE container?
简答 - 有。 Weld 可以允许在您希望可注入的任何对象旁边注入,但是您需要注意 who owns/manages 这个对象。在你的例子中,它是 EntityManager
这是来自 JPA 的东西,所以猜猜是什么 - JPA 管理此类对象的生命周期。因此,您需要为将由 CDI/Weld 处理的此类对象创建一个 "wrapper"(实际上它是一个代理)。这就是你需要 producer 的原因。
as if the annotation @PersistenceContext was ignored.
确实被忽略了。这是对所发生情况的简化。通常,在 EE 容器中,Weld 会使注入发生,但背后真正的魔力不是 Weld 核心代码,而是 EE 服务器端的集成(谁采用 Weld SPI 来处理此类注释并将它们转换为 bean然后注入)。
一般来说,尝试在 EE 容器之外处理 'EE stuff' 可能会很棘手,因为您会遇到很多最初发生在容器内部的集成,但现在您需要自己处理。
从技术上讲,可能可以使 @PersistenceContext
注释起作用,也许可以通过编写 CDI extension。然而,这是一个令人讨厌的 hack,而不是其他任何东西 - 人们会为了 SE 使用而弯曲 EE-only 注释。我会反对它,但如果你仍然想那样做,这个想法基本上是让 CDI 认为 @PersistanceContext 是另一个 @Inject 加上提供生产者。这将意味着大量的手动工作,CDI 中没有内置机制来为您处理 - 这通常是 EE 服务器的责任。