简体   繁体   English

如何正确锁定和重新加载实体

[英]How to lock and reload an entity correctly

In my web application I have several threads that potentially access the same data concurrently why I decided to implement optimistic (versioning) and pessimistic locking with Hibernate.在我的 web 应用程序中,我有几个线程可能同时访问相同的数据,为什么我决定使用 Hibernate 实现乐观(版本控制)和悲观锁定。

Currently I use the following pattern to lock an entity and perform write operations on it (using Springs Transaction manager and transaction demarcation with @Transactional):目前我使用以下模式来锁定一个实体并对其执行写操作(使用 Springs 事务管理器和@Transactional 的事务划分):

@Transactional
public void doSomething(entity) {
    session.lock(entity, LockMode.UPGRADE);
    session.refresh(entity);

    // I change the entity itself as well as entites in a relationship.
    entity.setBar(...);
    for(Child childEntity : entity.getChildren()) {
        childEntity.setFoo(...);
    }
}

However, sometimes I am getting StaleObjectException when the @Transactional is flushing that tells me that a ChildEntity has been modifed concurrently and now has a wrong version.但是,有时当@Transactional 正在刷新时我会收到StaleObjectException ,这告诉我 ChildEntity 已同时被修改并且现在版本错误。

I guess I am not correctly refreshing entity and its children so I am working with stale data.我想我没有正确刷新entity及其子项,所以我正在处理陈旧的数据。 Can someone point out how to achieve this?有人可以指出如何实现这一目标吗? Some thoughts of me included clearing the persistence context (the session) or calling session.lock(entity, LockMode.READ) again, but I am not sure what is correct here.我的一些想法包括清除持久性上下文(会话)或再次调用session.lock(entity, LockMode.READ) ,但我不确定这里什么是正确的。

Thanks for your help!谢谢你的帮助!

You may want to take at look at this Hibernate-Issue: LockMode.Upgrade doesn't refresh entity values .您可能想看看这个 Hibernate-Issue: LockMode.Upgrade doesn't refresh entity values

In short: Hibernat does NOT perform a select after a successful lock if the given entity was already preloaded.简而言之:如果给定的实体已经预加载,Hibernat 在成功锁定后不会执行 select。 You need to call refresh for the entity for yourself after you received the lock.收到锁后,您需要为自己调用实体的刷新。

Why do you make "LockMode.UPGRADE" and optimistic locking live together?为什么要让“LockMode.UPGRADE”和乐观锁定同时存在? Seem like controversial things.似乎是有争议的事情。

Hibernate never lock objects in memory and always use the locking mechanism of the database. Hibernate 从不锁定 memory 中的对象,始终使用数据库的锁定机制。 Also, "if the requested lock mode is not supported by the database, Hibernate uses an appropriate alternate mode instead of throwing an exception. This ensures that applications are portable.".此外,“如果数据库不支持请求的锁定模式,Hibernate 将使用适当的替代模式而不是抛出异常。这确保了应用程序是可移植的。”。 It means, that if your database doesn't support SELECT... FOR UPDATE, most probably, you will get these exceptions.这意味着,如果您的数据库不支持 SELECT... FOR UPDATE,您很可能会遇到这些异常。

Another possible reason is that you haven't used "org.hibernate.annotations.CascadeType.LOCK" for children.另一个可能的原因是您没有为孩子使用“org.hibernate.annotations.CascadeType.LOCK”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM