开发者

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.

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):

@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 ChildEn开发者_开发百科tity has been modifed concurrently and now has a wrong version.

I guess I am not correctly refreshing entity and its children so I am working with stale data. 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.

Thanks for your help!


You may want to take at look at this 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. 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? Seem like controversial things.

Hibernate never lock objects in memory and always use the locking mechanism of the database. 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.". It means, that if your database doesn't support SELECT ... FOR UPDATE, most probably, you will get these exceptions.

Another possible reason is that you haven't used "org.hibernate.annotations.CascadeType.LOCK" for children.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜