I present to you the translation of the fifth chapter of the official documentation Hibernate .Article translation is relevant for the version Hibernate 4.2.19.FinalPrevious chapter -
Hibernate Developer Documentation - Chapter IV. Batch processingNext chapter -
Hibernate Developer Documentation - Chapter VI. Caching')
Content5.1. Optimistic locks5.1.1 Dedicated version number5.1.2. Timestamp5.2. Pessimistic locksLocks are measures to prevent data from being modified in a relational database between the time it is read and the time it is used.
The blocking strategy can be either optimistic or pessimistic.
Blocking strategiesOptimisticOptimistic locks assume that multiple transactions can complete without affecting each other, and thus can be executed without locking the resources they affect. Before a commit, each transaction verifies that no other transaction has modified its data. If the check reveals conflicting modifications, the transaction in the commit state is rolled back.
PessimisticA pessimistic strategy implies that parallel transactions will conflict with each other, and requires blocking resources after reading them, as well as removing them only after the application has finished using the data.
Hibernate provides mechanisms for implementing both locking strategies in your application.
5.1. Optimistic locks
You can store versioned data when your application uses long-lived transactions or dialogs that span multiple transaction databases. Thus, if the same entity will be modified by two dialogs, the last dialog that commits the changes will be notified of the conflict and will not overwrite the results of another dialog. This approach guarantees a certain degree of isolation, but at the same time it scales well and shows itself quite well in situations of
Read-Often Write-SometimesHibernate provides two different mechanisms for storing versioned information — a dedicated version number, or a
timestamp .
Version numberTimestampImportantThe version or timestamp property cannot be null for detached objects. Hibernate recognizes any instance with a version (or timestamp) equal to null as transient , regardless of the other unsaved-value * strategies you specify. Declaring a null version or timestamp property is an easy way to avoid problems with Hibernate's transitive reattachment , which is especially useful in cases where you use assigned identifiers or composite keys.
* unsaved-value - strategy for defining an UPDATE or INSERT operation for synchronization with the database, depending on the value of the property being projected using id, version, or timestamp (approx. transl.)
5.1.1. Dedicated version number
The version number mechanism for optimistic locks is provided by Version annotation.
Example 5.1. Version annotation@Entity public class Flight implements Serializable { ... @Version @Column(name="OPTLOCK") public Integer getVersion() { ... } }
Here, the version property is mapped to the OPTLOCK column, and the
entity manager (
entity manager ) uses it to identify conflicting updates and prevent the loss of updates that would be overwritten by the
last-commit-wins strategy.
The version column can be of any type, provided that you define and implement the appropriate
UserVersionType .
Your application is not allowed to change the version number provided by Hibernate. To artificially increase the version number, see the description of the
LockModeType.OPTIMISTIC_FORCE_INCREMENT or
LockModeType.PESSIMISTIC_FORCE_INCREMENT properties in the Hibernate Entity Manager documentation. If the version number is generated by a database, such as a trigger, use the
org.hibernate.annotations.Generated (GenerationTime.ALWAYS) annotation.
Example 5.2. The version property declaration in hbm.xml <version column="version_column" name="propertyName" type="typename" access="field|property|ClassName" unsaved-value="null|negative|undefined" generated="never|always" insert="true|false" node="element-name|@attribute-name|element/@attribute|." />
Name | Description |
---|
column | The name of the column in which the version number is located. Optionally, the default is the same as the property name. |
name | The name of the property of the persistent class. |
type | Type of version number. Optional default integer. |
access | Hibernate strategy for accessing the property value. Optionally, the default property |
unsaved-value | Indicates that the instance has just been created and thus not saved. Distinguishes from detached entities. The default value, undefined , indicates that the identifier property should not be used. Optional. |
generated | Indicates that the version property should be generated by the database. Optionally, the default is never. |
insert | Include or not the version column in the SQL-insert expression. By default, true, but you can set this to false if the column in the database is defined with a default value of 0 |
5.1.2. Timestamp
Timestamps are a less reliable way to optimize locks than version numbers, which can also be used by applications for other purposes. Time stamps are used automatically if you use the
Version annotation on a
Date or
Calendar property.
Example 5.3. Using timestamps for optimistic locks @Entity public class Flight implements Serializable { ... @Version public Date getLastUpdate() { ... } }
Hibernate can extract the timestamp value from the database or JVM by reading the
org.hibernate.annotations.Source annotation
value . The value can be either
org.hibernate.annotations.SourceType.DB , or
org.hibernate.annotations.SourceType.VM . The default behavior is to use a database, also used if you do not specify an annotation.
The timestamp can also be generated by the database instead of Hibernate if you use the
org.hibernate.annotations.Generated (GenerationTime.ALWAYS) annotation.
Example 5.4. The timestamp element in hbm.xml <timestamp column="timestamp_column" name="propertyName" access="field|property|ClassName" unsaved-value="null|undefined" source="vm|db" generated="never|always" node="element-name|@attribute-name|element/@attribute|." />
Name | Description |
---|
column | The name of the column in which the timestamp is located. Optionally, by default same as property name. |
name | The name of the JavaBeans property of type Date or Timestamp of the persistent property. |
access | The strategy that Hibernate uses to access the value of a property. Optionally, the default property. |
unsaved-value | Indicates that the instance has just been created and thus not saved. Allocates from detached entities (detached). The default value, undefined, shows That property-id should not be used. Optional.
|
source | Whether Hibernate extracts a tag from the database or from the current JVM. DB labels add an additional overhead, as Hibernate needs to query the database each time to determine the increment. However, DB labels are safer when used in clustered environment. Not all DB dialects support extracting current timestamps from a DB. Others may be unsafe for locks, due to lack of accuracy.
|
generated | Whether tags are generated by the database. Optionally, the default is never. |
5.2. Pessimistic locks
The
LockMode class defines the different levels of locks that Hibernate can capture.
- LockMode.WRITE
Captured automatically when Hibernate updates or inserts a string. - LockMode.UPGRADE
It is captured after an explicit user request using SELECT ... FOR UPDATE on a database that supports this syntax. - LockMode.UPGRADE_NOWAIT
Captured after an explicit user request using SELECT ... FOR UPDATE NOWAIT in Oracle - LockMode.READ
It is captured automatically when Hibernate reads data under isolation levels Repeatable Read or Serializable. May be re-captured by explicit user request. - LockMode.NONE
No lock All objects are switched to this lock mode at the end of the transaction. Objects associated with the session
via the update () or saveOrUpdate call also starts in this mode.
The explicit user request indicated above occurs as a result of any of the following:
- Call Session.load () , indicating LockMode
- Call Session.lock ()
- Calling Query.setLockMode ()
If you call
Session.load () with the UPGRADE or UPGRADE_NOWAIT option, and the requested object has not yet been 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 strict lock than the one you requested, Hibernate will call
lock () for that object.
Session.lock () checks the version number in READ, UPGRADE, or UPGRADE_NOWAIT modes. In the cases of UPGRADE or UPGRADE_NOWAIT, the SELECT ... FOR UPDATE syntax will be used.
If the requested lock mode is not supported by the database, Hibernate will use the appropriate alternate mode instead of throwing an exception. This ensures application portability.