如何用Hibernate检测事务冲突?

时间:2009-09-21 11:37:08

标签: hibernate transactions hibernate-entitymanager staleobjectstate

我正在使用Hibernate 2.6和hibernate-entitymanager。我试图捕获和处理2个事务与对象冲突的情况。以下是发生的事情:

两个线程正在更新具有@Version字段的单个对象。失败提交竞争的线程在flush上记录StaleObjectStateException。不会抛出异常,只是记录它。我猜这个交易在那个时刻被标记为仅回滚。

之后,当线程尝试执行提交时,它会因RollbackException而失败。我没有找到一种方法来查找代码中回滚事务的原因。

有没有办法在代码中捕获和处理这种情况?基本上我想捕获StaleObjectStateException,但问题是 - 它没有被抛出。

更新:我想从鸟瞰图中完成的事情如下:

我有一个在JBoss下运行的J2EE应用程序。它有一些内部定时器调用的服务和从UI调用的服务。它还有一个关键实体。我需要确保不同的线程不能同时更新该实体类的对象,因为它可能导致数据不一致。这就是我实现乐观锁定的原因。

当出现optimistick锁定问题时,我正试图处理这种情况。我想在非常高的级别捕获它并显示有效的用户消息(在我的情况下,最高级别是RestEasy的ExceptionMapper)。问题是 - 当我捕获RollbackException时 - 已经太晚了。

我不会手动冲洗。我的大多数EJB都使用CMT,会话会自动刷新。

2 个答案:

答案 0 :(得分:2)

阿尔乔姆,

你能简单解释一下你想要实现的目标吗?鸟瞰图,很明显 - 就像这个(从中调用)UI代码?或者它是服务器端进程(因此您可以直接控制线程)?我问的原因是我从这个和你的其他相关问题中得到了一个(可能是不正确的)感觉,你试图使用乐观锁定来解决它不适合的事情,这就是导致所有麻烦的原因。

StaleObjectStateException而言,它绝对是从处理显式/隐式刷新的DefaultFlushEventListenerAutoFlushEventListener抛出的。你手动调用flush()吗?如果没有,也许异常被自动刷新的包装代码捕获/记录(Spring?TransactionManager?EntityManager?)

<强>更新

感谢您澄清问题。我仍然有点不清楚是否要阻止多个线程同时修改 1 同一个实体或阻止多个用户尝试同时编辑它。

前景可以通过乐观锁定来处理;但是如果没有明确的flush(),它就变成了非确定性的(首先使得修改的线程可能不会先被刷新/提交)。有关详细信息,请参阅我对this question的回答。自动刷新的另一个问题是您当前遇到的问题 - 在刷新之前不会发现失败的版本检查,如果该刷新与尝试提交事务一致,则抛出的异常是RollbackException。无论哪种方式,整个事务都会回滚。

后期场景(阻止用户编辑)不能通过乐观锁定来处理。您需要实现悲观锁定 - 在数据库或应用程序级别。换句话说,这个过程是:

  1. 用户想要编辑实体
  2. 检查实体
  3. 上是否存在锁定
  4. 是 - 禁止编辑(允许只读视图?)
  5. 否 - 锁定实体,允许编辑
  6. 提交(取消)更改;释放锁
  7. 如果您采用这种方法,请确保在用户不活动一段时间后使现有锁定失效。


    同时修改 1 在这种情况下并不准确(这就是交易的目的);我们正在谈论防止一个线程根据旧版本覆盖另一个线程的编辑。

答案 1 :(得分:0)

看看NHProf。它可以帮助您处理与Nhibernate分析相关的所有事情。