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

Transaction needed if multiple EJB methods called?

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

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

两种 ejbs 方法都操作相同的复杂 jpa 实体 bean 对象(包括刷新和分离)。我在数据库中认识到,当在 ejb1.op2() 之前调用 ejb1.op1() 时,一些 @oneToMany 关系形成了我的实体 bean,其中重复了。 我知道两个 ejbs 都开始了一个新的事务。到目前为止,对我来说一切看起来都还不错。 但 JSF 代码只有在我将 UserTransaction 添加到我的 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中。为什么这是必要的?

您需要用户交易吗?一般来说,容器管理的事务已经足够好了,可以达到目的。

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

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

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

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

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

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

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

无需在客户端中 fiddle 和 UserTransaction。在设计良好的基于​​ JSF 的客户端应用程序中,您也不应该需要它。

至于交易的原因,它会锁定数据库,以防您对实体执行业务操作。你的错误在于你完全独立地执行了两个明显相关的业务活动。这可能在高并发系统中确实会导致数据库状态损坏,就像您自己遇到的那样。

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