使用merge保存对象时获取HibernateOptimisticLockingFailureException

时间:2013-11-07 13:57:02

标签: hibernate nhibernate nhibernate-mapping

我有一个spring-hibernate应用程序,我正在尝试使用merge保存对象。有时我会得到HibernateOptimisticLockingFailureException。

我试图解决这个问题 1)在父对象和子对象之间使用“inverse = true”的双向映射。

2)使用TimeStamp或Version列添加对乐观锁定的支持 3)通过Id再次加载对象,然后合并修改后的数据。 4)使用save而不是merge 5)保存前锁定对象,保存后锁定释放。

我一直试图解决这个问题一周但没有成功。

有人可以帮忙吗?

注意:我正在使用hibernate3

1 个答案:

答案 0 :(得分:1)

使用乐观锁定时会出现间歇性错误。您需要添加代码来处理错误。

乐观的并发代码就像是,

  

“我非常肯定,甚至乐观,在我使用它的时候没有其他人会触及这一行。因此,我不会'悲观地'锁定这一行。那样我不会妨碍那些只想阅读这一行的人。虽然我不是傻瓜,所以在我写更改之前我会仔细检查,以确保没有其他人更新这行而我不是如果他们这样做了,我会提出错误而不是写下我的更改。“

最终结果与悲观方法基本相同;更新正在以有序的方式进行。除非现在非编写者正在经历更好的读取性能。但是,如果有很多东西试图同时编辑相同的行,那么它们迟早会相互踩踏。如果它发生得足够,这对写入性能来说可能非常糟糕,因为编写者必须继续重试才能成功。

你说,

  

“但是等等!SQL更新是原子的!两个更新怎么可能'互相踩'?”

我很高兴你问。请花点时间阅读 What happens if 2 or more people update a record at the exact same time?


大!你回来了。我们还有一些事情需要讨论。

什么时候应该使用悲观锁定而不是乐观并发?嗯,这些名字都说明了一切。当您乐观地认为并发更新通常不会发生时,请使用乐观并发。另一方面,如果您对并发更新一直发生非常悲观,请使用悲观锁定,以便数据库服务器负责确保每个人都排队等待轮到他们。

如果出现乐观的并发冲突,我的代码应该怎么做?基本上,它只需要重试直到它通过。最简单的方法是向用户显示一条消息,

  

“抱歉,此记录已更改。您的更改无法保存。请重新加载页面然后重试。”

这使得用户有责任弄清楚应该如何解决冲突。缺点是,他将不得不重新进入他的变化。

您可以使用在循环中自动重试的代码,直到它没有收到该错误,或​​者仍然使用代码检查已保存的其他更改并尝试智能地将更改合并在一起。如果你真的必须开始编写这样的代码,这可能是一个很好的迹象表明你会更好地使用悲观锁定。

其他什么,啰嗦一个?好吧,请记住,如果Hibernate或NHibernate抛出异常,你需要抛弃Session和相关实体并获得新实体。他们现在对数据库的外观有不一致的描述。您可能已回滚数据库事务,但未回滚这些内存中对象的状态。如果这是一个Web应用程序,并且您正在执行Session-per-request,,那么您将采用“告诉用户'对不起'”的方法,然后用户点击再次“保存”按钮。