我正在使用Hibernate 2.6和hibernate-entitymanager。我试图捕获和处理2个事务与对象冲突的情况。以下是发生的事情:
两个线程正在更新具有@Version字段的单个对象。失败提交竞争的线程在flush上记录StaleObjectStateException。不会抛出异常,只是记录它。我猜这个交易在那个时刻被标记为仅回滚。
之后,当线程尝试执行提交时,它会因RollbackException而失败。我没有找到一种方法来查找代码中回滚事务的原因。
有没有办法在代码中捕获和处理这种情况?基本上我想捕获StaleObjectStateException,但问题是 - 它没有被抛出。
更新:我想从鸟瞰图中完成的事情如下:
我有一个在JBoss下运行的J2EE应用程序。它有一些内部定时器调用的服务和从UI调用的服务。它还有一个关键实体。我需要确保不同的线程不能同时更新该实体类的对象,因为它可能导致数据不一致。这就是我实现乐观锁定的原因。
当出现optimistick锁定问题时,我正试图处理这种情况。我想在非常高的级别捕获它并显示有效的用户消息(在我的情况下,最高级别是RestEasy的ExceptionMapper)。问题是 - 当我捕获RollbackException时 - 已经太晚了。
我不会手动冲洗。我的大多数EJB都使用CMT,会话会自动刷新。
答案 0 :(得分:2)
阿尔乔姆,
你能简单解释一下你想要实现的目标吗?鸟瞰图,很明显 - 就像这个(从中调用)UI代码?或者它是服务器端进程(因此您可以直接控制线程)?我问的原因是我从这个和你的其他相关问题中得到了一个(可能是不正确的)感觉,你试图使用乐观锁定来解决它不适合的事情,这就是导致所有麻烦的原因。
就StaleObjectStateException
而言,它绝对是从处理显式/隐式刷新的DefaultFlushEventListener
和AutoFlushEventListener
抛出的。你手动调用flush()吗?如果没有,也许异常被自动刷新的包装代码捕获/记录(Spring?TransactionManager?EntityManager?)
<强>更新强>
感谢您澄清问题。我仍然有点不清楚是否要阻止多个线程从同时修改 1 同一个实体或阻止多个用户尝试同时编辑它。
前景可以通过乐观锁定来处理;但是如果没有明确的flush()
,它就变成了非确定性的(首先使得修改的线程可能不会先被刷新/提交)。有关详细信息,请参阅我对this question的回答。自动刷新的另一个问题是您当前遇到的问题 - 在刷新之前不会发现失败的版本检查,如果该刷新与尝试提交事务一致,则抛出的异常是RollbackException。无论哪种方式,整个事务都会回滚。
后期场景(阻止用户编辑)不能通过乐观锁定来处理。您需要实现悲观锁定 - 在数据库或应用程序级别。换句话说,这个过程是:
如果您采用这种方法,请确保在用户不活动一段时间后使现有锁定失效。
同时修改 1 在这种情况下并不准确(这就是交易的目的);我们正在谈论防止一个线程根据旧版本覆盖另一个线程的编辑。
答案 1 :(得分:0)
看看NHProf。它可以帮助您处理与Nhibernate分析相关的所有事情。