2

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.

1
  • I also have this problem. In my case I am aware that there could be another thread writing to the entity but I want my current method to trump all of those other methods. Alternatively my plan is to retry the current method if I get a org.hibernate.StaleObjectStateException Commented Oct 9, 2018 at 20:56

4 Answers 4

2

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.
Sign up to request clarification or add additional context in comments.

1 Comment

can you please elaborate on the 2.nd option? In my case, I need to use @Version attribute for the specific field. However in one of the use-cases, I need to set it's value manually (and prevent beeing overwritten)
1

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.

1 Comment

it's not a read-only operation! look at the comment in the code: //add contact properties to the model to be displayed later . He's manipulating the entity, so Hibernate tries to write that back to the database. It's a design flaw in OP's code, IMO.
0

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.

Comments

0

If I understand your code correctly you're manipulating the entity in your "read-only display page":

//add contact properties to the model to be displayed later

I guess, these are properties only used for display purpose, calculated before displaying them - but not meant to be saved in the database? If so, you shouldn't define these properties in your entity! Hibernate will try to write them back in the database (Did you even define those database columns?).

Here are your alternatives:

  • Map your entity to a DTO/POJO class before returning it in your Controller. That new class can contain properties you only need for display purposes.
  • Detach the entity from the EntityManager. So calling any Setters on it will not cause update calls to the database.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.