[[locking]]
== Locking
:sourcedir: ../../../../../test/java/org/hibernate/userguide/locking
:extrasdir: extras

In a relational database, locking refers to actions taken to prevent data from changing between the time it is read and the time is used.

Your locking strategy can be either optimistic or pessimistic.

Optimistic::
http://en.wikipedia.org/wiki/Optimistic_locking[Optimistic locking] assumes that multiple transactions can complete without affecting each other,
and that therefore transactions can proceed without locking the data resources that they affect.
Before committing, each transaction verifies that no other transaction has modified its data.
If the check reveals conflicting modifications, the committing transaction rolls back.
Pessimistic::
Pessimistic locking assumes that concurrent transactions will conflict with each other,
and requires resources to be locked after they are read and only unlocked after the application has finished using the data.

Hibernate provides mechanisms for implementing both types of locking in your applications.

=== Optimistic

When your application uses long transactions or conversations that span several database transactions,
you can store versioning data so that if the same entity is updated by two conversations, the last to commit changes is informed of the conflict,
and does not override the other conversation's work.
This approach guarantees some isolation, but scales well and works particularly well in _read-often-write-sometimes_ situations.

Hibernate provides two different mechanisms for storing versioning information, a dedicated version number or a timestamp.

[NOTE]
====
A version or timestamp property can never be null for a detached instance.
Hibernate detects any instance with a null version or timestamp as transient, regardless of other unsaved-value strategies that you specify.
Declaring a nullable version or timestamp property is an easy way to avoid problems with transitive reattachment in Hibernate,
especially useful if you use assigned identifiers or composite keys.
====

[[locking-optimistic-version-number]]
=== Dedicated version number

The version number mechanism for optimistic locking is provided through a `@Version` annotation.

[[locking-optimistic-version-number-example]]
.@Version annotation
====
[source, JAVA, indent=0]
----
include::{sourcedir}/OptimisticLockingTest.java[tags=locking-optimistic-version-number-example]
----
====

Here, the version property is mapped to the `version` column, and the entity manager uses it to detect conflicting updates,
and prevent the loss of updates that would otherwise be overwritten by a last-commit-wins strategy.

The version column can be any kind of type, as long as you define and implement the appropriate `UserVersionType`.

Your application is forbidden from altering the version number set by Hibernate.
To artificially increase the version number, see the documentation for properties `LockModeType.OPTIMISTIC_FORCE_INCREMENT` or
`LockModeType.PESSIMISTIC_FORCE_INCREMENT` check in the Hibernate Entity Manager reference documentation.

[NOTE]
====
If the version number is generated by the database, such as a trigger, use the annotation `@org.hibernate.annotations.Generated(GenerationTime.ALWAYS)` on the version attribute.
====

[[locking-optimistic-timestamp]]
=== Timestamp

Timestamps are a less reliable way of optimistic locking than version numbers, but can be used by applications for other purposes as well.
Timestamping is automatically used if you the `@Version` annotation on a `Date` or `Calendar` property type.

[[locking-optimistic-version-timestamp-example]]
.Using timestamps for optimistic locking
====
[source, JAVA, indent=0]
----
include::{sourcedir}/OptimisticLockingTest.java[tags=locking-optimistic-version-timestamp-example]
----
====

Hibernate can retrieve the timestamp value from the database or the JVM, by reading the value you specify for the `@org.hibernate.annotations.Source` annotation.
The value can be either `org.hibernate.annotations.SourceType.DB` or `org.hibernate.annotations.SourceType.VM`.
The default behavior is to use the database, and is also used if you don't specify the annotation at all.

The timestamp can also be generated by the database instead of Hibernate, if you use the `@org.hibernate.annotations.Generated(GenerationTime.ALWAYS)` annotation.

[[locking-pessimistic]]
=== Pessimistic

Typically, you only need to specify an isolation level for the JDBC connections and let the database handle locking issues.
If you do need to obtain exclusive pessimistic locks or re-obtain locks at the start of a new transaction, Hibernate gives you the tools you need.

[NOTE]
====
Hibernate always uses the locking mechanism of the database, and never lock objects in memory.
====

[[locking-LockMode]]
=== `LockMode` and `LockModeType`

Long before JPA 1.0, Hibernate already defined various explicit locking strategies through its `LockMode` enumeration.
JPA comes with its own http://docs.oracle.com/javaee/7/api/javax/persistence/LockModeType.html[`LockModeType`] enumeration which defines similar strategies as the Hibernate-native `LockMode`.

[cols=",",, options="header"]
|=======================================================================
|`LockModeType`|`LockMode`|Description

|`NONE`|`NONE` |The absence of a lock. All objects switch to this lock mode at the end of a Transaction. Objects associated with the session via a call to `update()` or `saveOrUpdate()` also start out in this lock mode.
|`READ` and `OPTIMISTIC`|`READ` | The entity version is checked towards the end of the currently running transaction.
|`WRITE` and `OPTIMISTIC_FORCE_INCREMENT`|`WRITE` | The entity version is incremented automatically even if the entity has not changed.
|`PESSIMISTIC_FORCE_INCREMENT`|`PESSIMISTIC_FORCE_INCREMENT` | The entity is locked pessimistically and its version is incremented automatically even if the entity has not changed.
|`PESSIMISTIC_READ`|`PESSIMISTIC_READ` | The entity is locked pessimistically using a shared lock, if the database supports such a feature. Otherwise, an explicit lock is used.
|`PESSIMISTIC_WRITE`|`PESSIMISTIC_WRITE`, `UPGRADE` | The entity is locked using an explicit lock.
|`PESSIMISTIC_WRITE` with a `javax.persistence.lock.timeout` setting of 0 |`UPGRADE_NOWAIT` | The lock acquisition request fails fast if the row s already locked.
|`PESSIMISTIC_WRITE` with a `javax.persistence.lock.timeout` setting of -2 |`UPGRADE_SKIPLOCKED` | The lock acquisition request skips the already locked rows. It uses a `SELECT ... FOR UPDATE SKIP LOCKED` in Oracle and PostgreSQL 9.5, or `SELECT ... with (rowlock, updlock, readpast) in SQL Server`.
|=======================================================================

The explicit user request mentioned above occurs as a consequence of any of the following actions:

* a call to `Session.load()`, specifying a `LockMode`.
* a call to `Session.lock()`.
* a call to `Query.setLockMode()`.

If you call `Session.load()` with option `UPGRADE`, `UPGRADE_NOWAIT` or `UPGRADE_SKIPLOCKED`,
and the requested object is not already loaded by the session, the object is loaded using `SELECT ... FOR UPDATE`.

If you call `load()` for an object that is already loaded with a less restrictive lock than the one you request, Hibernate calls `lock()` for that object.

`Session.lock(`) performs a version number check if the specified lock mode is `READ`, `UPGRADE`, `UPGRADE_NOWAIT` or `UPGRADE_SKIPLOCKED`.
In the case of `UPGRADE`, `UPGRADE_NOWAIT` or `UPGRADE_SKIPLOCKED`, the `SELECT ... FOR UPDATE` syntax is used.

If the requested lock mode is not supported by the database, Hibernate uses an appropriate alternate mode instead of throwing an exception.
This ensures that applications are portable.

[[locking-jpa-query-hints]]
=== JPA locking query hints

JPA 2.0 introduced two query hints:

javax.persistence.lock.timeout:: it gives the number of milliseconds a lock acquisition request will wait before throwing an exception
javax.persistence.lock.scope:: defines the http://docs.oracle.com/javaee/7/api/javax/persistence/PessimisticLockScope.html[_scope_] of the lock acquisition request.
The scope can either be `NORMAL` (default value) or `EXTENDED`. The `EXTENDED` scope will cause a lock acquisition request to be passed to other owned table structured (e.g. `@Inheritance(strategy=InheritanceType.JOINED)`, `@ElementCollection`)

[[locking-jpa-query-hints-timeout-example]]
.`javax.persistence.lock.timeout` example
====
[source, JAVA, indent=0]
----
include::{sourcedir}/ExplicitLockingTest.java[tags=locking-jpa-query-hints-timeout-example]
----

[source, SQL, indent=0]
----
include::{extrasdir}/locking-jpa-query-hints-timeout-example.sql[]
----
====

[NOTE]
====
Not all JDBC database drivers support setting a timeout value for a locking request.
If not supported, the Hibernate dialect ignores this query hint.
====

[NOTE]
====
The `javax.persistence.lock.scope` is https://hibernate.atlassian.net/browse/HHH-9636[not yet supported] as specified by the JPA standard.
====

[[locking-buildLockRequest]]
=== The `buildLockRequest` API

Traditionally, Hibernate offered the `Session#lock()` method for acquiring an optimistic or a pessimistic lock on a given entity.
Because varying the locking options was difficult when using a single `LockMode` parameter, Hibernate has added the `Session#buildLockRequest()` method API.

The following example shows how to obtain shared database lock without waiting for the lock acquisition request.

[[locking-buildLockRequest-example]]
.`buildLockRequest` example
====
[source, JAVA, indent=0]
----
include::{sourcedir}/ExplicitLockingTest.java[tags=locking-buildLockRequest-example]
----

[source, SQL, indent=0]
----
include::{extrasdir}/locking-buildLockRequest-example.sql[]
----
====

[[locking-follow-on]]
=== Follow-on-locking

When using Oracle, the https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#SQLRF55371[`FOR UPDATE` exclusive locking clause] cannot be used with:

- `DISTINCT`
- `GROUP BY`
- `UNION`
- inlined views (derived tables), therefore, affecting the legacy Oracle pagination mechanism as well.

For this reason, Hibernate uses secondary selects to lock the previously fetched entities.

[[locking-follow-on-example]]
.Follow-on-locking example
====
[source, JAVA, indent=0]
----
include::{sourcedir}/ExplicitLockingTest.java[tags=locking-follow-on-example]
----

[source, SQL, indent=0]
----
include::{extrasdir}/locking-follow-on-example.sql[]
----
====

[NOTE]
====
To avoid the N+1 query problem, a separate query can be used to apply the lock using the associated entity identifiers.
====

[[locking-follow-on-secondary-query-example]]
.Secondary query entity locking
====
[source, JAVA, indent=0]
----
include::{sourcedir}/ExplicitLockingTest.java[tags=locking-follow-on-secondary-query-example]
----

[source, SQL, indent=0]
----
include::{extrasdir}/locking-follow-on-secondary-query-example.sql[]
----
====

The lock request was moved from the original query to a secondary one which takes the previously fetched entities to lock their associated database records.
