我将 EJB 3 与 Hibernate 一起使用。我有一个无状态会话 Bean。该 bean 中有一个方法 deleteItem。
当客户端调用 deleteItem 方法时,删除发生没有任何问题。但是,如果我尝试使用 for 循环调用 deleteItem 方法并将该循环的限制设置为 5-10 次,那么有时删除会失败。但不总是。
删除操作实际上是从 2 个表中删除数据。子表和父表。每个 Delete 都是通过执行刷新操作来提交的。
正如我已经提到的,如果我一个一个地执行删除,那么就不会发生问题,只有当我尝试同时运行它时才会发生。我得到的例外如下
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 并再次重新执行删除操作。我检查了异常类名称,它是 EntityNotFound。但我看到在堆栈跟踪中我得到了 OptimisticLockException 和 StaleObjectStateException。
那么,有人可以指导我如何捕捉这个 OptimisticLockException 吗?