Hibernate:它是不是在 get() 之后使用 LockOptions.UPGRADE 重新加载对象

Posted

技术标签:

【中文标题】Hibernate:它是不是在 get() 之后使用 LockOptions.UPGRADE 重新加载对象【英文标题】:Hibernate : Does it reload the object after get() with LockOptions.UPGRADEHibernate:它是否在 get() 之后使用 LockOptions.UPGRADE 重新加载对象 【发布时间】:2016-05-16 09:59:14 【问题描述】:

我遇到了一个问题,我使用get(Serializable,Class,LockOptions) 方法和LockOptions.UPGRADE 获取行上的锁。

正在获取锁的对象已经存在于会话中。 执行 select ... for update 后,我发现如果表中的相应行在初始获取对象之后和get(Serializable,Class,LockOptions) 之前已更改,则该方法不会返回更新的对象。

我想澄清以下内容, 这是因为我试图在其对象已加载到会话缓存中的行上获取锁。

Hibernate 是否只是在后台触发 select ... for update,但不重新加载对象,而是从会话缓存中获取一个对象(如果找到)?

以下是关于我如何获取锁的代码 sn-p。

List<MyObject> listOfMyObject = dao.getListOfMyObjects();

for(MyObject m : listOfMyObject )
   m = session.get(id,MyObject.class,LockOptions.UPGRADE);
   //

锁定机制工作正常。当锁被 ThreadOne 事务持有时,我可以看到另一个 ThreadTwo 事务正在等待获取锁。现在当 ThreadOne 事务释放锁时,第二个事务通过session.get(id,MyObject.class,LockOptions.UPGRADE) 方法获取它,返回的对象没有 ThreadOne 完成的更新值。

【问题讨论】:

【参考方案1】:

理想情况下,当您使用 LockOptions.Upgrade 时,它​​是一种悲观锁定。

理想情况下,它不应该允许任何其他事务来更改记录,因为它是对该数据库行的一种悲观锁定。

理想情况下,不要使用悲观锁定,而是通过使用某种版本/时间戳列来进行乐观锁定,您可以在其中以编程方式进行更多控制。

【讨论】:

【参考方案2】:

是的,根据Hibernate docs,session.get(Serializable,Class,LockOptions) 从会话中加载该实例(如果它已经存在)。对于您的情况,您可能希望在 session.get(Serializable,Class,LockOptions) 之后立即使用 session.refresh(Object object) 从数据库中重新读取实例的状态。

【讨论】:

以上是关于Hibernate:它是不是在 get() 之后使用 LockOptions.UPGRADE 重新加载对象的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate SqlResultSetMapping 相同的结果重复而不是唯一

hibernate之4.延迟载入

Hibernate session.createCriteria 与 session.get 性能

使用hibernate.get()取得对象再set()属性后调用update()更新对象时一直不能写入到数据库,是啥原因?

hibernate学习——加载策略(优化)

Hibernate 中get()与load()方法的区别