我在Hibernate中使用EJB 3。 我有一個無狀態的會話Bean。該bean中有一個方法deleteItem。無法捕捉Hibernate OptimisticLockException
當客戶端調用deleteItem方法時,發生的刪除沒有任何問題。 但如果我試圖使用for循環調用deleteItem方法,並將該循環的限制設置爲5-10次,那麼有時候刪除失敗。但不總是。
刪除操作實際上從2個表中刪除數據。子表和父表。 每個刪除通過執行刷新操作來提交。
正如我已經提到,如果我一個一個執行刪除,那麼沒有問題發生,它只發生在我試圖同時運行它。我得到的例外是
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key
constraint fails (`functionTest/MotherTable`, CONSTRAINT `FKBC6CB0E6D5545EFD` FOREIGN KEY
(`MotherTable_FieldId`) REFERENCES `ChildTable` (`childTableId`))
在這裏沒有辦法發生併發刪除操作。而項目刪除與其他項目刪除操作無關。因此,如果仍然發生併發,那麼同時刪除多個項目不會成爲問題。
所以,我來到一個決定 - 「可能是客戶端正在訪問多線程中的同一個Bean實例」。在這種情況下,兩個線程保持相同的實體管理器狀態處於不同的狀態。當另一個還沒有完成刪除子項目時,會嘗試刷新持久性上下文。 此時發生BatchUpdateException。 - 這是我的觀察。我不是100%確定的。
所以爲了克服這種情況,我去了樂觀鎖定。我在母表中創建了版本列。現在我得到了OptimisticLockException。但我無法捕捉到這個例外。下面是我用來捕獲OptimisticLockException的代碼。
private boolean deleteItem(Item itemId) {
Item item= getItem(itemId);
removeChildTableData(item);
mEm.remove(item);
try
{
mEm.flush();
}
catch (OptimisticLockException e)
{
try {
Thread.sleep(1000);
}
catch (InterruptedException e1) {
e1.printStackTrace();
}
deleteItem(itemId);
}
catch(Exception ex)
{
if (ex.getCause() instanceof OptimisticLockException)
{
try {
Thread.sleep(1000);
} catch (InterruptedException x) {
}
deleteItem(itemId);
}
}
return true;
}
所以我的目標是趕上OptimisticLockException並再次執行刪除操作。 我檢查了Exception Class Name,它是EntityNotFound。但我看到在堆棧跟蹤中,我得到了OptimisticLockException以及StaleObjectStateException。
那麼,任何人都可以請指導我如何抓住這個OptimisticLockException?
我認爲一個完整的堆棧跟蹤將有很大幫助,因爲重要的是,異常來自哪裏。 – wildhemp
您應該相信錯誤消息所說的內容。如果它說外鍵約束被破壞,則意味着外鍵約束被破壞。增加樂觀的愛好不會改變任何事情。而且您不應該嘗試捕獲樂觀鎖定異常並繼續使用相同的會話和實體。它不會工作。閱讀http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#transactions-demarcation-exceptions –
@JBNizet - 我明白你的觀點。但問題是它並不總是發生。它只發生在併發發生時。是的,你是對的,在處理樂觀鎖異常之後,我應該在新的事務中運行它。 – ifti24