本地方法调用中的EJB事务

时间:2009-01-09 09:02:25

标签: java-ee transactions ejb

在以下设置中,方法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调用)

3 个答案:

答案 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

我想你能做的最好的事情就是测试它来验证它! :)