problem with hibernate cache

Solution Unverified - Updated -

Issue

  • Our application uses hibernate (the one delivered with jboss) for saving\loading data from the database.We recently run into a problem that we fail to update a row in a table with the Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect).

  • We are using the hibernate version control on the entity:

  • The scenario that causes the problem is when we use two threads to update the same row as followed:

    Each thread start its own database transaction.
    Both threads reads the record from the database (for this example assume initial version is 10).
    Both threads request a lock on this record (our own locking mechanism).
    Thread 1 gain the lock and thread 2 wait for the lock to be released.
    Thread 1 update the record and commit the transaction.
    At this point we can see in sqlplus the the version increased to 11.
    Thread 1 release the lock.
    Thread 2 get the lock and request a fresh copy of the entity.
    At this point we can see the the version in the fresh copy is still 10.
    Thread 2 try to update the record, but failed since the version on the record is not 10.

  • Just for testing we tried to do session.clear() before thread 2 reads a fresh copy. In that case the fresh copy will contain the updated data and everything will work.

  • It seems to me that doing a session.clear() can have other unwanted effects. Can please advise on what should we do?

  • At the beginning both threads load the same entity so in both sessions the the version is the same (and in the first level of Hibernate cache). When the first thread modify the entity and save it to the database it does change the version.

  • However now when the second thread try to get a fresh copy of the entity it still get the same one (before the change of the first thread) - This is from the first level cache.

  • In order to get a fresh copy we needed to remove the item from the cache and then reload from database that seems to solve the problem.

  • We managed to identify the problem before it occur by checking the version of the item we want to save and the one return from the database and if it is not the same we remove the item from the Hibernate first lever cache and try to reload it (due to some issues we had, we first flush the pending commands to the database and only then clear the cache).

The end result is:

if (versions are not as expected) {
    session.flush();
    session.evict(item);
    item = session.load(...);
}

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 5.2.0

Subscriber exclusive content

A Red Hat subscription provides unlimited access to our knowledgebase of over 48,000 articles and solutions.

Current Customers and Partners

Log in for full access

Log In