【发布时间】:2017-08-17 04:28:50
【问题描述】:
例如用作 cdi 应用程序范围的 bean 是否应该包含 jpa 读/写内容,或者我应该始终将 EJB 用于 db 内容?我在互联网上的某个地方读到 cdi 不应包含 db 的东西。这是真的吗?
【问题讨论】:
-
一般来说,一个句子在互联网上并不能成为一个好问题。您可以在问题中添加一些上下文吗?
-
好的,我添加了更多,请看一下
例如用作 cdi 应用程序范围的 bean 是否应该包含 jpa 读/写内容,或者我应该始终将 EJB 用于 db 内容?我在互联网上的某个地方读到 cdi 不应包含 db 的东西。这是真的吗?
【问题讨论】:
是的,如果您使用任何 JavaEE 7 plus 版本或 JakartaEE,您可以使用 @Transactional InterceptorBinding 管理 CDI bean 上的数据库内容
看看Javadoc:@Transactional
以下是注入 EntityManager 和 CDI 而没有 EJB 的步骤
首先创建一个生产者来产生EntityManager。
public class EntityManagerProducer {
@PersistenceContext(name = "customer-orders-unit")
private EntityManager em;
@Produces
@RequestScoped
public EntityManager getEntityManager() {
return em;
}
}
创建您的 bean 以执行 DAO 操作。
public MyCDIBeanDao{
@Inject
private EntityManager m_entityManager;
@Transactional
public doStuff(){
// Here you are in a Container managed Transaction
m_entityManager.persist(...)
}
}
不要忘记将beans.xml 添加到您的WEB-INF 文件夹中。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
bean-discovery-mode="all"
version="2.0">
</beans>
【讨论】:
答案总是取决于...这取决于您的具体用例。
在 Java EE 中,我们使用 @EJB bean 作为注入 EntityManager 以便稍后在 JPA 实体上执行读/写的地方。
我们为什么这样做?因为我们需要Transactions。默认情况下,当您使用 @Stateless 注释 bean 时,其中的所有方法都是 Transactional 并且您可以免费获得它们。事务使您能够以原子方式更新多个表,它们要么全部成功,要么失败。
示例:
在您的方法updateABC()您想要更新表 A、B、C 并且您希望它们全部成功或回滚事务:
@Stateless
public class MyClass{
@PersistenceContext
EntityManager em;
public void updateABC(){
A a= em.find(A.class, aId);
//here update some fields on the entity "a"
B b= em.find(B.class, bId);
//here update some fields on the entity "b"
C c= em.find(C.class, cId);
//here update some fields on the entity "c"
}
}
就是这样……你已经完成了。您的所有更新都将神奇地保存到数据库中,否则什么也不会。
你需要这样的东西吗?去 EJB 的。 你不需要?您想手动完成这项工作吗?然后创建自己的 bean...
【讨论】:
@TransactionalInterceptorBinding,你无事可做。只需注释您的方法(在容器管理的 bean 上)即可。它是 EJB 事务管理的替代方案。而且你不必管理 UseTransaction,这就是拦截器所做的。