Java EE7 由一堆“bean”定义组成:
- 托管 Beans 1.0 (JSR-316/JSR-250)
- Java 1.0 (JSR-330) 的依赖注入(inject)
- CDI 1.1 (JSR-346)
- JSF 托管 Bean 2.2 (JSR-344)
- EJB 3.2 (JSR-345)
为了摆脱脑海中的困惑,我研究了几篇“什么时候使用哪种bean类型”的文章。 EJB 的优点之一似乎是它们单独支持声明性容器管理事务(著名的事务注释)。不过,我不确定这是否正确。有人可以批准吗?
与此同时,我想出了一个简单的演示应用程序来检查这是否真的是真的。我刚刚基于 this 定义了一个 CDI bean(不是 一个 EJB - 它没有类级别注释),如下所示片段:
public class CdiBean {
@Resource
TransactionSynchronizationRegistry tsr;
@Transactional(Transactional.TxType.REQUIRED)
public boolean isTransactional() {
return tsr.getTransactionStatus() == Status.STATUS_ACTIVE;
}
}
现在,GlassFish 4.0 的结果是该方法实际上返回 true,根据我的询问,它没有按预期工作。我确实希望容器忽略 CDI bean 方法上的 @Transactional 注释,甚至抛出异常。我使用的是新安装的 GlassFish 4 服务器,因此没有任何干扰。
所以我的问题是:
- 哪些 bean 类型实际上支持容器管理的事务?
- 出于好奇,如果上面的代码有误,我该如何用一个简单的演示应用程序来测试它?
(顺便说一句:有人描述了类似的问题 here ,但它的解决方案不适用于我的情况。
最佳答案
在 Java EE 7 之前,只有 EJB 是事务性的,并且 @Transactional
注释不存在。
从 Java EE 7 和 JTA 1.2 开始,您可以在 CDI 中使用带有 @Transactional
注释的事务拦截器。
要回答您关于使用哪种 bean 的最佳类型的问题,默认情况下答案是 CDI。
CDI bean 比 EJB 更轻,并且支持很多功能(包括作为 EJB)并且默认激活(当您将 beans.xml
文件添加到您的应用程序时)。
由于 Java EE 6 @Inject
取代了 @EJB
。即使您使用远程 EJB(CDI 中不存在的功能),最佳实践建议您 @EJB
一次以注入(inject)远程 EJB 和 CDI 生产者将其公开为 CDI bean
public class Resources {
@EJB
@Produces
MyRemoteEJB ejb;
}
对于 Java EE 资源也建议这样做
public class Resources2 {
@PersistenceContext
@Produces
EntityManager em;
}
这些生产者将在以后使用
public class MyBean {
@Inject
MyRemoteEJB bean;
@Inject
EntityManager em;
}
EJB 继续对它们包含的某些服务(如 JMS 或异步处理)有意义,但您会将它们用作 CDI bean。
关于java - JEE7 : Do EJB and CDI beans support container-managed transactions?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17838221/