Locking refers to actions taken to prevent data in a relational database from changing between the time it is read and the time that it is used.
Your locking strategy can be either optimistic or pessimistic.
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.
Your locking strategy can be either optimistic or pessimistic.
Locking strategies
- Optimistic
- 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[1].
- 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
Hibernate provides two different mechanisms for storing versioning information, a dedicated version number or a timestamp.
- Version number
- Timestamp
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.
Here, the version property is mapped to the
OPTLOCK
column, and the entity manager uses it to detect conflicting updates, and prevent the loss of updates that would 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 orLockModeType.PESSIMISTIC_FORCE_INCREMENTcheck in the Hibernate Entity Manager reference documentation.
- If the version number is generated by the database, such as a trigger, use the annotation
@org.hibernate.annotations.Generated(GenerationTime.ALWAYS)
. - 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 eitherorg.hibernate.annotations.SourceType.DB
ororg.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. -
LockMode.WRITE acquired automatically when Hibernate updates or inserts a row.LockMode.UPGRADE acquired upon explicit user request usingSELECT ... FOR UPDATE
on databases which support that syntax.LockMode.UPGRADE_NOWAIT acquired upon explicit user request using aSELECT ... FOR UPDATE NOWAIT
in Oracle.LockMode.READ acquired automatically when Hibernate reads data under Repeatable Read orSerializable isolation level. It can be re-acquired by explicit user request.LockMode.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 toupdate()
orsaveOrUpdate()
also start out in this lock mode.
Comments
Post a Comment