Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ChildEntity 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!

like image 396
Erik Avatar asked Jul 14 '11 10:07

Erik


1 Answers

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.

like image 130
Mario Gleichmann Avatar answered Oct 11 '22 22:10

Mario Gleichmann