How to temporarily disable the Hibernate entity version checking?

2.4k views Asked by At

I have a page where I display all contacts. This is just the read only page and all I do is iterate through all contacts for some group and display them:

//Not lazy load of contacts, I cannot use lazy loading
List<Contact> contacts = someService.getContacts(groupId);

for (Contact contact : contacts) {
    //add contact properties to the model to be displayed later
}

At the same time I might have a separate, background thread which updates one of the contacts. The thread updates a field that I'm not going to display, so I'm perfectly OK with data desynchronising in this case.

The problem is the Hibernate will update the contact's version number and commit it to my db (when the background thread finishes). So when my for loop hits such an object the following exception will be thrown.

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

Which is perfectly ok. Is there a way to disable object's version checking during iteration through a hibernate's collection? When I say disable, I mean in this particular scenario, in this particular for loop? But not other situations.

I think it happens because the underlying collection is the AbstractPersistentCollection and its iterator will check each member's version with corresponding db value.

3

There are 3 answers

1
Vlad Mihalcea On

You cannot disable optimistic locking on a session-basis, but there are some alternatives to handle this situation:

  1. You can switch to versionless optimistic locking
  2. You can map multiple Entity fragments to the same table, and you can have a fragment that only contains the columns you need for a particular business case and with no version. This way you can bypass the regular Entity optimistic locking check.
0
codedabbler On

If you are doing a read-only operation, then you should not get a StaleObjectStateException. This exception is thrown when you are doing an update with data that is stale and Hibernate detects it using the version information.

So check your code and make sure that you are not doing any unneeded updates from your read-only operation of displaying the contacts.

0
sanemain On

Here are 2 solutions I could come up in addition to the ones described in other answers:

  • Use native sql update in the thread to update the Contact entity and do not increment the version number.
  • Extract the updated fields into a separate entity and do not include @Version in that entity. In a normal transaction (triggered from end user request) updating Contacts, use OPTIMISTIC_FORCE_INCREMENT hint. This hint forces the Contact version number increment even if you only update the extracted entity. The other thread mentioned can update the extracted entity without any hint or so.

Both solutions have cons and they seem equally ugly to me. I feel the same for solutions mentioned in other answers. I believe JPA should provide more flexibility in how it handles optimistic version control.