我得到了由容器管理的会话 bean。最近我遇到问题,抛出异常:
org.hibernate.StaleObjectStateException:行被另一个事务更新或删除(或未保存值映射不正确)
这是因为其他一些进程已更新行(并且版本字段已更改)。现在,当它被抛出时,我捕获了 OptimisticLockException 并想重新运行失败的操作(这次我想放置 WRITE 锁以确保它不会再次失败),我这样做:
T ctj = new T();
C ca = entityManager.find(C.class, id);
Double newBalance = Operations.add(ca.getAccountBalance(), amount);
ca.setAccountBalance(newBalance);
entityManager.persist(ca);
ctj.setBalanceAfterTransaction(newBalance);
entityManager.persist(ctj);
try {
flushRegisterTransactionUpdateAccountBalance();
} catch(OptimisticLockException ex) {
retryBalanceUpdate(ca, ctj, amount);
}
以及我在上面调用的方法:
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private void retryBalanceUpdate(C ca, T ctj, Double amount) {
entityManager.refresh(ca);
entityManager.lock(ca, LockModeType.WRITE);
Double newBalance = Operations.add(ca.getAccountBalance(), amount);
ca.setAccountBalance(newBalance);
entityManager.persist(ca);
ctj.setBalanceAfterTransaction(newBalance);
entityManager.persist(ctj);
flushRegisterTransactionUpdateAccountBalance();
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private void flushRegisterTransactionUpdateAccountBalance() {
entityManager.flush();
}
我已经创建了这两种方法,因为我希望整个(父)事务不会因为 flushRegisterTransactionUpdateAccountBalance() 引发的异常而失败。
不幸的是它失败了,当我调用 catch 块方法 retryBalanceUpdate 时,它的主体 (entityManager.refresh(ca)) 的第一行抛出:
[TxPolicy] javax.ejb.EJBTransactionRolledbackException:EntityManager 必须在事务内访问 [MyBean] 无事务 javax.persistence.TransactionRequiredException:EntityManager 必须在事务内访问
有谁知道我怎样才能实现我所解释的?我使用的是 EJB 3.0,entityManager 对象由类级注释启动:
@PersistenceContext(unitName="MyPersistenceUnit") 私有 EntityManager entityManager;
它自己的类是具有事务属性 SUPPORTS 的无状态会话 bean