我有一个带有bean管理事务的无状态bean,以及这样的方法:
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class ... {
@Resource
private UserTransaction ut;
@EJB
private OtherStatelessBeanLocal other;
public void invokeSomeMethods()
ut.begin();
...
// invoke other bean's methods here.
other.method();
...
ut.commit();
}
}
那么UserTransaction
如何传播到OtherStatelessBeanLocal
bean?
答案 0 :(得分:32)
UserTransaction
对象是容器提供的对象,它包装对容器内部使用的API调用的访问,特别是javax.transaction.TransactionManager。 TransactionManager
包含begin
,commit
,rollback
和javax.transaction.Transaction getTransaction()
在幕后,TransactionManager将使用ThreadLocal或类似技术来跟踪线程的当前事务状态。 ThreadLocals是非常简单的对象,很容易被描述为static HashMap
,它使用线程名称作为键,并将您选择的对象用作值。只要您保持在同一个线程中,就可以从调用链中的任何位置获取对象。这是不允许在Java EE环境中启动线程的原因之一。
安全传播以类似的方式工作,JNDI查找也神奇地指向正确的模块或组件的java:comp/env
命名空间。底线是你没有ThreadLocals就无法实现app服务器。传播听起来比它更活跃,实际上它只是不离开线程的行为所以容器和所有参与者仍然可以找到你的“东西”。
回到事务管理术语中,TransactionManager将在其ThreadLocal中跟踪的对象通常(直接或间接)实现Transaction和TransactionSynchronizationRegistry接口。在这两个接口之间,容器具有代表您在当前事务中跟踪DataSource
,EntityManager
和其他资源所需的所有挂钩。这些接口还允许容器提供诸如SessionSynchronization之类的回调,以及在事务完成时代表您执行其他操作的方法,例如刷新/关闭EntityManagers,发送JMS挂起消息以及持久保存由您创建的任何计时器。应用程序在交易过程中。
答案 1 :(得分:4)
基于EJB规范,您不能使用程序化事务将编程事务中的事务上下文(在本例中是您的主类...)传递到另一个bean(在本例中为其他),使用程序化事务
答案 2 :(得分:0)
对于EJB3,您通常使用@TransactionAttribute批注定义事务传播。
所有EJB 3.0应用程序的默认事务属性都是必需的:
如果客户端在客户端与事务上下文关联时调用企业bean的方法,则容器在客户端的事务上下文中调用企业bean的方法。
交易类型的文档位于:http://download.oracle.com/javaee/6/api/javax/ejb/TransactionAttributeType.html
N.B。持久化上下文和事务传播通常一起发生但并非总是 - 要小心。例如,有状态会话bean可能有extended persistence context。