我正在尝试用CMT完全理解JTA的划分。我遇到的行为是,在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
答案 0 :(得分:2)
我对EJB 3规范的解读是,单个方法的事务规范会覆盖整个EJB的事务规范。因此,您所要求的期望应该是合理的,但是......
仅当您将bean方法用作EJB时才会这样做。当你从一个业务方法doAction()直接调用另一个,save()时,你没有使用EJB引用,因此这只是普通的旧Java - 容器没有涉及,所以容器没有机会干预
如果你对doAction()方法应用了必需的选项,我希望这可以工作。
这个理论与您对重构到另一个EJB的影响的结果一致。