如果调用多个EJB方法,需要事务吗?

时间:2015-01-11 12:34:59

标签: jpa jsf-2 transactions ejb

我的问题是如果调用多个EJB方法,则需要在JSF Bean中定义UserTransaction。 这是我的一般情况:

//jsf bean...
@EJB ejb1;
...
public String process(businessobject) {
  ejb1.op1(businessobject);
  ejb1.op2(businessobject);
  ....
}

两个ejbs方法都操纵相同的复杂jpa实体bean对象(包括flush和detachment)。我在数据库中认识到,在ejb1.op2()之前调用ejb1.op1()时,某些@oneToMany关系形成了我的实体bean。 据我所知,两个ejbs都开始了新的交易。对我来说到目前为止看起来还不错。 但是,只有将UserTransaction添加到我的jsf方法中,JSF代码才能正常工作:

//jsf bean...
@Resource UserTransaction tx;
@EJB ejb1;
...
public String process(businessobject) {
  try {
    tx.begin();
    ejb1.op1(businessobject);
    ejb1.op2(businessobject);
  finaly {
      tx.commit();
  }....
}

我没想到有必要将两个ejb调用封装到一个usertransaction中。为什么这有必要?

2 个答案:

答案 0 :(得分:2)

来自客户端的每个@Stateless EJB方法调用(在您的情况下,JSF托管bean),默认情况下确实计为一个完整事务。这种情况持续到EJB方法调用返回为止,包括嵌套的EJB方法调用

如果它必须代表单个事务,则将它们合并到单个EJB方法调用中。

public String process(Entity entity) {
    ejb1.op1op2(entity);
    // ...
}

public void op1op2(Entity entity) {
    op1(entity);
    op2(entity);
}

无需在客户端中使用UserTransaction。在一个设计良好的基于​​JSF的客户端应用程序中,你也应该永远不需要它。

关于事务的原因,它会锁定数据库,以防您在实体上执行业务操作。你的错误在于你完全独立地完成了两个明显依赖的商业行为。这可能在高并发系统中确实导致您自己遇到的损坏的DB状态。

关于交易的原因,这可能是一个很好的阅读:When is it necessary or convenient to use Spring or EJB3 or all of them together?

答案 1 :(得分:1)

您需要进行用户交易吗?通常,容器管理的交易足够好并且可以达到目的。

即使您需要拥有用户管理的事务,将事务管理逻辑与JSF逻辑混合也不是一件好事。

对于使用容器管理的事务,您应该查看在EJB上使用@TransactionAttribute。

如果ejb中的所有方法都需要具有相同级别的事务支持,则可以在类级别获得注释。否则,您还可以对每个单独的ejb方法使用@TransactionAttribute注释。