如前所述
我们需要有一个前端 Seam 组件(非 EJB)调用多个 DAO (EJB) 方法并将它们全部包装在一个事务中
但
我们的事务由容器处理- 也称为容器管理事务(容器负责调用每个底层资源管理器事务使用的开始和提交方法)
第一个问题是您有一个非 EJB 调用多个 DAO 的场景,每个 DAO 都是一个 EJB。你可以想到
@Name("nonEjbComponent")
public class NonEjbComponent {
private @In DaoEjbComponent daoEjbComponent;
private @In OtherDaoEjbComponent otherDaoEjbComponent;
private @In AnotherDaoEjbComponent anotherDaoEjbComponent;
private @In UserTransaction userTransation;
public void wrapperAllOfThem() {
userTransation.begin();
daoEjbComponent.save(someEntity);
otherDaoEjbComponent.update(otherEntity);
anotherDaoEjbComponent.delete(anotherEntity);
userTransation.commit();
}
}
但是 Java EE 规范 3.0 指出
具有 bean 管理或容器管理的事务划分的企业 bean必须是会话 bean 或消息驱动的 bean。
所以你不能使用上面的场景。而且因为你所有的 DAO 都使用容器管理的事务,Java EE 规范不允许你同时使用容器管理和 bean 管理的事务
所以解决方案是
将所有 DAO 包装在一个 EJB 无状态会话 bean 中,该会话 bean的事务是容器管理的。它将表现得像一个委托组件
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Name("wrapperStateless")
public class WrapperStatelessImpl implements WrapperStateless {
private @In DaoEjbComponent daoEjbComponent;
private @In OtherDaoEjbComponent otherDaoEjbComponent;
private @In AnotherDaoEjbComponent anotherDaoEjbComponent;
public void wrapperAllOfThem() {
daoEjbComponent.save(someEntity);
otherDaoEjbComponent.update(otherEntity);
anotherDaoEjbComponent.delete(anotherEntity);
}
}
在您的非 EJB 组件中,使用
@Name("nonEjbComponent")
public class NonEjbComponent {
private @In WrapperStateless wrapperStateless;
public void wrapperAllOfThem() {
wrapperStateless.wrapperAllOfThem();
}
}