2013-10-11 59 views
0

我得到了由包含者管理的會話bean。最近,我遇到的問題,在這裏拋出異常:EJB:CMT,拋出後如何重試操作

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(); 
} 

這些2種方法我都裝箱,因爲我希望是因爲()由flushRegisterTransactionUpdateAccountBalance拋出的異常的整個(父)交易不會失敗。

不幸的是失敗,當我在catch塊方法retryBalanceUpdate調用,它的第一行的機身(entityManager.refresh(CA))拋出:

[TxPolicy] javax.ejb.EJBTransactionRolledbackException:EntityManager的必須訪問在一個事務中 [爲myBean]無交易 javax.persistence.TransactionRequiredException:EntityManager的必須是在一個事務中訪問

是否anybode知道我怎麼能實現我解釋?我使用的是EJB 3.0,entityManager對象是由類級註釋啓動的:

@PersistenceContext(unitName =「MyPersistenceUnit」)private EntityManager entityManager;

類它的自我是無狀態會話bean與交易屬性支持

回答

0

OptimisticLockException:

當一個樂觀鎖衝突發生持久性提供拋出。此異常可能會作爲API調用的一部分,即刷新或提交時引發。 當前 交易(如果有一個處於活動狀態)將被標記爲回滾

您可以使用註釋@ApplicationException(rollback=false)創建自定義異常。在flushRegisterTransactionUpdateAccountBalance你必須趕上OptimisticLockException &重新拋出自定義異常。

可以參考下面的示例代碼。

try { 
    flushRegisterTransactionUpdateAccountBalance(); 
} catch(XApplicationException ex) { 
    retryBalanceUpdate(ca, ctj, amount); 
} 

在下面的代碼,處理異常&然後重新拋出,其被標記爲回滾=假定製的異常。

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
private void flushRegisterTransactionUpdateAccountBalance() throws XApplicationException{ 
    try { 
    entityManager.flush(); 
    } catch(OptimisticLockException ex) { 
    throw new XApplicationException(ex.getMessage()); 
} 
}