Hibernate Versionless Optimistic Locking
This article is about a Hibernate feature called versionless optimistic locking. Versionless optimistic locking is an alternative to using JPA’s
@Version annotation with a numeric or timestamp column. It can be used to lower the risk of optimistic locking exceptions.
Optimistic locking with Hibernate is commonly implemented by applying the
@Version annotation to a
version instance variable resulting in a
VERSION column with either a numberic value or a timestamp (depending on the declared type of the instance variable).
Although this is sufficient in many situations, Hibernate does provide alternative locking strategies too. By applying the
@OptimisticLocking annotation on type level you can define the style of optimistic locking to be applied to a JPA entity.
The example above shows the default locking strategy. When having a look at the
OptimisticLockType (JavaDoc) enumeration, we can see the following locking strategies:
DIRTY define so-called versionless locking strategies.
OptimisticLockType.ALL is given in the
@OptimisticLocking#type attribute, the optimistic lockingn strategy works as follows: whenever an
DELETE statement is generated by Hibernate, it will append not only the
@Id column in its
WHERE clause but also all of the persistent fields.
Let’s say our
Car class would look like
let us consider we have an already persisted
Car instance and we would change property
OptimisticLockType.ALL the generated SQL statement would be
All columns of the associated database row are used in the WHERE clause. If the
Car instance would have been changed in the meantime and the
UPDATE would not find a row, a
StaleStateException or an
OptimisticLockException is going be thrown.
OptimisticLockType.DIRTY only the dirty/changed fields (in our case
model) would be part of the SQL statement
model column still has the same value the
UPDATE will succeed.
With such an optimistic locking strategy, the main advantage is that it reduces the potential of overlapping updates. When using
OptimisticLockType.DIRTY, the documentation advises to use the
@SelectBeforeUpdate annotations in combination with
@DynamicUpdate will generate
UPDATE statements only
SETting the dirty columns,
@SelectBeforeUpdate will avoid issues with detached entities, assuming the Hibernate session is opened for the entire request.
Besides the commonly known versioning optimistic locking strategy, Hibernate comes with two other versionless strategies this article has a closer look at.