UserTransaction如何传播?
我有一个带有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?
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挂起消息以及在应用程序中保留应用程序创建的任何计时器交易。
基于EJB规范,您不能使用程序化事务将编程事务中的事务上下文(在本例中是您的主类…)传递到另一个bean(在本例中为其他)
对于EJB3,通常使用@TransactionAttribute批注定义事务传播。
所有EJB 3.0应用程序的缺省事务属性都是必需的:
如果客户端在客户端与事务上下文关联时调用企业bean的方法,则容器将在客户端的事务上下文中调用企业bean的方法。
交易类型的文档位于: http : //download.oracle.com/javaee/6/api/javax/ejb/TransactionAttributeType.html
NB持久性上下文和事务传播通常一起发生但并非总是 – 要小心。 例如,有状态会话bean可能具有扩展的持久性上下文 。