【发布时间】:2013-03-24 00:15:05
【问题描述】:
我将 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 ?
【问题讨论】:
-
我认为完整的堆栈跟踪会有很大帮助,因为重要的是,异常来自哪里。
-
您应该相信错误消息所说的内容。如果它说外键约束被破坏,则意味着外键约束被破坏。添加乐观的爱不会改变任何事情。而且您不应该尝试捕获乐观锁定异常并继续使用相同的会话和实体。它行不通。阅读docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/…
-
@JBNizet - 我明白你的意思。但问题是它并不总是发生。它仅在并发发生时发生。是的,你是对的,在处理完乐观锁异常后,我应该在新事务中运行它。
标签: java hibernate jakarta-ee jpa ejb