我有一个无状态bean,例如:
@Stateless
public class MyStatelessBean implements MyStatelessLocal, MyStatelessRemote {
@PersistenceContext(unitName="myPC")
private EntityManager mgr;
@TransationAttribute(TransactionAttributeType.SUPPORTED)
public void processObjects(List<Object> objs) {
// this method just processes the data; no need for a transaction
for(Object obj : objs) {
this.process(obj);
}
}
@TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
public void process(Object obj) {
// do some work with obj that must be in the scope of a transaction
this.mgr.merge(obj);
// ...
this.mgr.merge(obj);
// ...
this.mgr.flush();
}
}
典型的用法是客户端调用 processObjects(...),它实际上并不与实体管理器交互。它做它需要做的事情,并为每个要处理的对象单独调用 process(...) 。process(...) 的持续时间相对较短,但 processObjects(...) 可能需要很长时间才能运行所有内容。因此我不希望它保持一个开放的交易。我确实需要单独的 process(...) 操作在他们自己的事务中操作。这应该是每次调用的新事务。最后,我想保持选项打开,让客户直接调用 process(...)。
我尝试了许多不同的事务类型:从不、不支持、支持(在 processObjects 上)和必需,需要新的(在进程上),但每次调用 merge() 时都会得到 TransactionRequiredException。
我已经能够通过将方法分成两个不同的 bean 来使其工作:
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {
@EJB
private MyStatelessBean2 myBean2;
public void processObjects(List<Object> objs) {
// this method just processes the data; no need for a transaction
for(Object obj : objs) {
this.myBean2.process(obj);
}
}
}
@Stateless
public class MyStatelessBean2 implements MyStatelessLocal2, MyStatelessRemote2 {
@PersistenceContext(unitName="myPC")
private EntityManager mgr;
@TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
public void process(Object obj) {
// do some work with obj that must be in the scope of a transaction
this.mgr.merge(obj);
// ...
this.mgr.merge(obj);
// ...
this.mgr.flush();
}
}
但我仍然很好奇是否有可能在一堂课上完成这项工作。在我看来,事务管理器仅在 bean 级别运行,即使为单个方法提供了更具体的注释也是如此。因此,如果我以某种方式标记一个方法以防止事务开始在同一实例中调用其他方法也不会创建事务,无论它们是如何标记的?
我正在使用 JBoss Application Server 4.2.1.GA,但欢迎/首选非特定答案。