0

在使用 java 持久性时,我需要澄清重试“可重试”异常(例如,锁定等待超时之类的东西)的正确方法。例如,使用如下伪代码:

EntityTransaction tx = em.getTransaction();
tx.begin();
for (a bunch of objects) {
  em.persist(object);
}
tx.commit();

如果数据库中有锁,我有时会在 em.persist 调用中抛出异常。我可以将其包装在 try/catch 中并重试(显然有一些计数)?还是我必须包装整个 tx.begin/commit 并重

谢谢

4

3 回答 3

1

假设锁定超时不是数据库死锁的解决方法,一个更简单的解决方案是对您的请求使用更长的超时。不要使用N第二个超时并重试C多次,而是将超时设置为N * (C + 1)秒。

(如果您使用锁定超时作为死锁的解决方法,那么您将遇到更大的问题。您最好尝试修复死锁的根本原因,因为即使C重试,您的事务也有可能会赢'不通过。)

于 2010-07-29T06:31:42.383 回答
0

如果您按照规范进行编程,您实际上应该处理整个 EntityManager 并重新开始。没有例外可以保证在 EM 级别“可重试”。如果persist() 方法出现异常,则您的整个持久性会话被认为是不一致/不确定的。

有时它会起作用。我知道在休眠中,您通常可以在乐观锁定异常后尝试获取收益。但总的来说,如果您尝试从 entitymanager 异常中捕获和恢复并保持相同的 entitymanager,那么您依赖的供应商特定行为可能定义不明确。

更多信息在这里。

于 2010-07-29T03:47:45.143 回答
0

只要 EntityManager 抛出的异常没有将事务标记为仅回滚(LockTimeoutException 就是这样一个例子,但 PessimisticLockException 不是),您就可以继续处理当前事务中的事情。

如果 TX 被标记为仅回滚,则您必须救助 TX,然后重试您在 TX 中发生错误之前尝试的任何操作并继续。

如果您要使用 JPA 在一个循环中处理大量事情,那么您很可能是 DELETE 或 UPDATE jpql 查询的理想人选。

于 2012-04-17T20:30:50.123 回答