Search code examples
jpatransactionslocking

JPA and optimistic locking modes


I read an article on the blog of Oracle here about JPA and locking modes.

I don't entirely understand the difference between OPTIMISTIC and OPTIMISTIC_FORCE_INCREMENT lock mode types.

OPTIMISTIC mode :

enter image description here

When a user locks an entity with this mode, a check is done on the version field entity (@version) at the beginning of transaction and a check on the version field is also done at the end of the transaction. If versions are different, the transaction rolls back.

OPTIMISTIC_FORCE_INCREMENT mode :

enter image description here

When a user chooses this mode, he has to flush() the state of EntityManager into database to increment the version field manually. Thus, all other optimistic transactions will be invalidated (roll back). A check on the version is also done at end of transaction to commit or roll back transaction.

It seems clear but when should I use OPTIMISTIC versus OPTIMISTIC_FORCE_INCREMENT modes ? The only criteria that I see is to apply OPTIMISTIC_FORCE_INCREMENT mode when I want the transaction to have precedence over the others because choosing this mode will roll back all other running transactions (if I understand well mecanism).

Is there other reason to choose this mode rather than OPTIMISTIC mode?

Thanks


Solution

  • Normally you would never use the lock() API for optimistic locking. JPA will automatically check any version columns on any update or delete.

    The only purpose of the lock() API for optimistic locking is when your update depends on another object that is not changed/updated. This allows your transaction to still fail if the other object changes.

    When to do this depends on the application and the use case. OPTIMISTIC will ensure the other object has not been updated at the time of your commit. OPTIMISTIC_FORCE_INCREMENT will ensure the other object has not been updated, and will increment its version on commit.

    Optimistic locking is always verified on commit, and there is no guarantee of success until commit. You can use flush() to force the database locks ahead of time, or trigger an earlier error.