在以下设置中,方法B是否在(新)事务中运行?
EJB,有两种方法,方法A和方法B
public class MyEJB implements SessionBean
public void methodA() {
doImportantStuff();
methodB();
doMoreImportantStuff();
}
public void methodB() {
doDatabaseThing();
}
}
EJB是容器管理的,require_new事务中的methodB和所需事务中的方法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调用方法A与EJB方法调用。 methodA现在在一个事务中运行。从methodA对methodB的后续调用是在同一个事务中运行,还是在新事务中运行? (记住,这是实际的代码。对方法B没有明确的ejb调用)
答案 0 :(得分:35)
您对methodB()
的调用是对方法的普通调用,不是由EJB容器拦截的;在运行时,EJB容器将注入proxy而不是类的实例,这是在调用方法之前拦截调用和设置环境的方式。如果您使用this
,则直接调用方法,而不是通过代理。因此,无论ejb-jar.xml中通过EJB接口进行调用的内容如何,两种方法都将使用相同的事务。
答案 1 :(得分:23)
注入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();
}
}
在“调用#1”中这是一个本地调用,不通过代理,它将返回计数
在'invocation#2'这是一个通过代理的调用,因此你注释它不支持事务 - 现在由create(user)方法打开 - 这个调用将抛出一个事务异常:
javax.ejb.EJBException:无法在全局事务中调用EJB
答案 2 :(得分:3)
他们将使用相同的交易。
如果我记得很清楚,事务是在调用方法之前由容器启动的,并在“完成”之后提交。
由于“a”称为“b”,“b”将使用相同的事务。
:S
我想你能做的最好的事情就是测试它来验证它! :)