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 session.createCriteria 与 session.get 性能
使用hibernate.get()取得对象再set()属性后调用update()更新对象时一直不能写入到数据库,是啥原因?