0

我试图完全理解 JTA 与 CMT 的划分。我遇到的行为是,在 EJB 上仅尊重该方法的第一个 @TransactionAttribute,而对具有不同 @TransactionAttribute 注释的同一 bean 的后续方法调用则没有。

例子:

@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class Foo implements IFoo {

   @EJB
   private IBar barBean;

   // inherits class transaction annotation of NOT_SUPPORTED
   public void doSomething() {
        barBean.doAction();
   }
}

@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class Bar implements IBar {

    public void doAction() {
        Entity entity = bar.find();
        entity.setName("new name");
        // fails with EJBException with TransactionRequiredException as cause
        save(entity);
    }

    public Entity find() {
        // return some persisted entity.
        return em.findById(1);
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public Entity save(entity) {
        em.persist(em.merge(entity));
        em.flush();
    }
}

我看到的行为是 Bar.save() 抛出 TransactionRequiredException。所以这告诉我在 save() 上设置的 REQUIRED 注释不会创建事务。REQUIRES_NEW 也不起作用。如果我将 save() 移动到另一个 EJB,它会按预期工作。

这是否意味着只有第一个 TransactionAttribute 注释被尊重,而不管后续方法调用是否具有不同的注释值?这是一个错误还是预期的行为?我似乎找不到任何具体解释这一点的文档。我很感激对此的任何见解。

我的堆栈:EJB 3.0、Toplink Essentials、GF V2UR2

4

1 回答 1

2

我对 EJB 3 规范的解读是,单个方法的事务规范会覆盖整个 EJB 的事务规范。因此,您对 REQUIRED 应该适用的期望似乎是合理的,但是......

仅当您将 bean 方法用作 EJB 时。当您从一个业务方法 doAction() 直接调用另一个业务方法 save() 时,您没有使用 EJB 引用,因此这只是普通的旧 Java - 不涉及容器,因此容器没有机会进行干预.

如果您将所需的选项应用于您的 doAction() 方法,我希望这可以工作。

这个理论与您对重构到另一个 EJB 的影响的发现一致。

于 2009-10-08T17:04:51.557 回答