首先,我想解释一下我在这种情况下的自调用 ejb 方法。我有一个有状态的会话 bean,它有一个启动新事务的方法(由 注释@REQUIRES_NEW
)。为了在bean本身内部调用这个方法并使注解生效,我使用SessionContext#getBusinessObject()
来实现@EJB
(@EJB
here会导致stackoverflow?!)的效果。我的代码如下所示:
@Stateful
@Local
public class TransactionTest implements ITransactionTest {
@PersistenceContext(unitName="Table",Type=PersistenceContextType.EXTENDED)
private EntityManager manager;
@Resource
SessionContext sc;
ITransactionTest me;
@PostConstruct
public void init(){
me = this.sc.getBusinessObject(ITransactionTest.class);
}
public void generateRecord(int i) throws RuntimeException{
Record record = new Record();
record.setId(i+"");
record.status(1);
manager.persist(record);
manager.flush(); //If not flush, result is correct. Why?
me.updateRecord(i);
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void updateRecord(int i) throws RuntimeException{
try {
Record record = manager.find(Record.class, i+"");
record.setStatus(2);
manager.flush();
} catch(Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
同时,generateRecord()
运行正常。控制台显示它毫无例外地执行“插入”和“更新”HQL(我使用 Hibernate 作为 JPA 提供程序)。但是,“更新”结果不会出现在数据库中。为什么?是否updateRecord()
正确提交?
另外,我以两种替代方式尝试它:首先是调用generateRecord()
(它将不再调用updateRecord()
),然后updateRecord()
是在另一个 bean 中连续调用。它可以给我正确的结果。
第二个是删除第一个flush()
。然后 'insert' 和 'update' HQL 都将在第二个执行flush()
。这种方法也可以产生正确的结果。
我的程序在 JBOSS 6.1.0-Final 下运行,数据库是 Oracle。
此致,
卡杰拉斯