本地方法调用中的EJB事务
在下面的设置中,方法B在(新)事务中运行吗?
一个EJB,有两种方法,方法A和方法B.
public class MyEJB implements SessionBean public void methodA() { doImportantStuff(); methodB(); doMoreImportantStuff(); } public void methodB() { doDatabaseThing(); } }
EJB是容器pipe理的,methodB在requires_new事务中,方法A在所需的事务中。 从而:
<container-transaction id="MethodTransaction_1178709616940"> <method id="MethodElement_1178709616955"> <ejb-name>MyName</ejb-name> <method-name>*</method-name> <trans-attribute>Required</trans-attribute> </method> <method id="MethodElement_1178709616971"> <ejb-name>MyName</ejb-name> <method-name>methodB</method-name> </method> <trans-attribute>RequiresNew</trans-attribute> </container-transaction>
现在让另一个EJB调用methodA调用EJB方法。 methodA现在运行在一个事务中。 从methodA的后续调用methodB运行在同一个事务中,还是运行在一个新的事务? (请注意,这里是实际的代码,没有明确的方法B的ejb调用)
您对methodB()
的调用是一个普通的方法调用,不会被EJB容器拦截; 在运行时EJB容器将注入一个代理而不是你的类的一个实例,这是它调用你的方法之前拦截调用和设置环境的方式。 如果你使用this
你直接调用一个方法,而不是通过代理。 因此,这两个方法都将使用相同的事务,而不pipeejb-jar.xml中通过EJB接口调用的内容。
注入SessionContext,并请求你的代理实例:
@Stateless public class UserFacade implements UserFacadeLocal { @Resource private SessionContext context; @Override @TransactionAttribute(TransactionAttributeType.REQUIRED) private void create(User user) { System.out.println("Users Count: "+count()); //invocation#1 System.out.println("Users Count Through Context: "+context.getBusinessObject(UserFacadeLocal.class).count()); //invocation#2 } @Override @TransactionAttribute(TransactionAttributeType.NEVER) public int count() { return ((Long) q.getSingleResult()).intValue(); } }
在'invocation#1'这是一个本地调用,不通过代理,它会返回计数
在'invocation#2'中这是一个通过代理的调用,因此你注释它不支持事务(现在由create(user)方法打开),这个调用将抛出一个事务exception:
javax.ejb.EJBException:在全局事务中不能调用EJB
他们将使用相同的交易。
如果我没记错的话,事务是由容器“之前”调用方法启动的,在“完成”之后提交。
由于“a”调用“b”,“b”将使用相同的事务。
:S
我想你能做的最好的事情就是testing它来validation它! 🙂