Lock (Locking)
In the process of implementing business logic, it is often necessary to guarantee the exclusivity of data access. such as in the final settlement of the financial system
Processing, we want to process the data for a cut-off point in time, and we don't want to be in the process of closing
(may be a few seconds, or maybe a few hours), and the data will change again. At this point, we need to pass some machine
System to ensure that this data is not modified by the outside world during an operation,
"Lock", that is, to lock the target data we have selected so that it cannot be modified by other programs.
Hibernate supports two types of locking mechanisms: commonly referred to as "pessimistic locks (pessimistic Locking)"
and "optimistic Lock (optimistic Locking)".
Pessimistic lock (Pessimistic Locking)
A pessimistic lock, as its name implies, is the data being externally (including other current transactions of the system, as well as from
External System Transaction) modification is conservative, so the data is locked during the entire data processing
State. The implementation of pessimistic locks often relies on the lock mechanism provided by the database (and only the lock mechanism provided by the database layer can
Truly guarantee the exclusivity of data access, otherwise, even in this system to implement the locking mechanism, there is no guarantee that the external system
Data is not modified).
A typical pessimistic lock call that relies on a database:
SELECT * from account where name= ' Erica ' for update
This SQL statement locks all records in the Account table that match the search criteria (name= "Erica").
These records cannot be modified by the outside world before the transaction commits (the locks in the transaction are freed during transaction commits).
Hibernate's pessimistic lock is also a database-based lock mechanism implementation.
The following code implements the locking of the query record:
String Hqlstr =
"From TUser as user where user.name= ' Erica '";
Query query = session.createquery (HQLSTR);
Query.setlockmode ("User", Lockmode.upgrade); Locking
List userlist = Query.list ();//execute query, get data
Query.setlockmode locks the records corresponding to specific aliases in the query statement (we
The TUser class specifies an alias "user", which is where all user records returned are locked.
Observe the SQL statements generated by Hibernate during the run time:
Select Tuser0_.id as ID, tuser0_.name as name, tuser0_.group_id
As group_id, Tuser0_.user_type as User_type, tuser0_.sex as Sex
From T_user tuser0_ where (tuser0_.name= ' Erica ') for update
Here Hibernate implements the pessimistic locking mechanism by using the database's for UPDATE clause.
Hibernate's lock modes are:
Ølockmode.none: no lock mechanism.
Ølockmode.write:hibernate automatically when Insert and Update records
Get.
The ølockmode.read:hibernate is automatically retrieved when the record is read.
These three locking mechanisms are typically used internally by hibernate, such as hibernate to ensure that the Update
The object is not modified by the outside world, and a WRITE lock is automatically added to the target object in the Save method implementation.
Ølockmode.upgrade: Use the database's for UPDATE clause to lock.
Ølockmode. Upgrade_nowait:oracle's specific implementation, leveraging Oracle's
The UPDATE nowait clause implements locking.
The above two kinds of locking mechanism is more commonly used in the application layer, lock is generally implemented by the following methods:
Criteria.setlockmode
Query.setlockmode
Session.lock
Note that it is only possible to set the lock before the query starts (that is, before hiberate generates SQL).
Lock processing is really done through the lock mechanism of the database, otherwise, the data has passed without the for update
Clause of the Select SQL is loaded, so-called database lock also can not be discussed.
Optimistic lock (optimistic Locking)
Relative pessimistic lock, the optimistic locking mechanism adopts a more relaxed locking mechanism. Pessimistic lock in most cases depending on the
The locking mechanism of the database is implemented to ensure the maximum degree of exclusivity of the operation. But it comes with the database.
The high cost of performance, especially for long transactions, is often unsustainable.
such as a financial system, when an operator reads a user's data, and on the basis of the read out user data is motivated
Changes, such as changing the user account balance, if a pessimistic locking mechanism is used, it means that the entire operation
Approached (the entire process of reading data from the operator, starting the modification until the result of the change is submitted, even including the operation
To cook coffee in the middle of the day), the database record is always in the lock state, you can imagine, if the face of a few
Hundreds of thousands of concurrent, such a situation will lead to what consequences.
The optimistic locking mechanism solves this problem to some extent. Optimistic locks, mostly based on the data version
(Version) Recording mechanism implementation. What is a data version? is to add a version ID to the data,
In a version solution for a database table, it is generally by adding a "version" field to the database table to
Realize.
When the data is read, the version number is read together, and then the version number is added one after the update. At this point, the proposed
Data is compared to the current version of the database table corresponding to the record, if the data submitted
The version number is newer than the current version number of the database table, otherwise it is considered to be outdated data.
For an example of modifying user account information above, assume that there is an account information table in the database
The version field, the current value is 1, and the Current Account balance field (balance) is $ $.
1 operator A reads it out at this time (version=1) and deducts the sum from its account balance
($100-$50).
2 during operator a operation, operator B also reads this user information (version=1), and
Deduct $ A ($100-$20) from its account balance.
3 operator a completed the modification work, adding a data version number one (version=2), together with the account buckle
After the balance (BALANCE=$50), submitted to the database update, at this time because the submission data version large
The database records the current version, the data is updated, and the database record version is updated to 2.
4 operator B completes the operation, and the version number plus one (version=2) attempts to submit a number to the database
(balance=$80), but at this time compared to the database record version, operator B commits the
The data version number is 2, the current version of the database record is also 2, and the "commit version must be greater than
The current version to perform an update ", so the submission of operator B is dismissed.
This prevents operator B from overwriting operations with the result of old data modifications based on Version=1
Result of the operation of the operator A.
As can be seen from the above example, the optimistic locking mechanism avoids the database lock overhead in a long transaction (operator A
And operator B during operation, there is no data locking to the database), which greatly improves the system under large concurrency
Overall performance.
It is important to note that the optimistic locking mechanism is often based on the data storage logic in the system, and therefore has a certain bureau
limitations, as in the above example, because the optimistic locking mechanism is implemented in our system, users from external systems
The balance update operation is not controlled by our system and may cause dirty data to be updated in the database. In
During the system design phase, we should take full account of the possibility of these situations and make appropriate adjustments (e.g.
The optimistic locking policy is implemented in the database stored procedure, and only the data update path based on this stored procedure is opened externally.
Rather than exposing the database tables directly to the public).
Hibernate has built-in optimistic locking implementations in its data access engine. If the external system logarithm is not considered
By using the transparent optimistic lock provided by Hibernate, it will greatly enhance our
Productivity.
Hibernate can be combined with the Optimistic-lock property of the class descriptor with version
Descriptor designation.
Now, let's add an optimistic locking mechanism to the TUser in the previous example.
1. First, add the Optimistic-lock property to the class descriptor for TUser:
<class
Name= Org.hibernate.sample.TUser "
table=" T_user "
Dynamic-update=" true "
Dynamic-insert=" true "
optimistic-lock= "Version"
;
...
</class>
optimistic-lock Property has the following selectable values:
Ønone
No optimistic lock
Øversion
implements optimistic locking through a versioning mechanism;
Ødirty
Enables optimistic locking by checking for changed properties
Øall
Optimistic locking by checking all properties
The optimistic locking mechanism, which is implemented through version, is an optimistic lock implementation that is officially recommended by Hibernate, and is also
is hibernate, the only lock machine that is still valid if the data object is removed from Session modification
System. Therefore, in general, we all choose the version mode as the Hibernate optimistic lock implementation mechanism.
2 . Add a Version property descriptor
<class
Name= "org.hibernate.sample.TUser"
Table = "T_user"
Dynamic-update= "true"
Dynamic-insert= "true"
optimistic-lock= "version"
;
<id
Name= "id"
column= "id"
type= "Java.lang.Integer"
;
<generator class= "native";
</generator>
</id>
<version
column= "Version"
Name= "Version"
Type= "Java.lang.Integer"
/>
......
</class>
Note The version node must appear after the ID node.
Here we declare a version property that holds the user's release information, stored in the TUser table's
The Version field.
At this point, if we try to write a piece of code, update the record data in the TUser table, such as:
Criteria = Session.createcriteria (Tuser.class);
Criteria.add (Expression.eq ("name", "Erica"));
List userlist = Criteria.list ();
TUser user = (TUser) userlist.get (0);
Transaction tx = Session.begintransaction ();
User.setusertype (1); Update Usertype Field
Tx.commit ();
Each time we update the TUser, we can see that the version in the database is incremented.
And if we try to start another Session before Tx.commit, the use of the name Erica
To emulate the Concurrency update scenario:
Session session= getsession ();
Criteria = Session.createcriteria (Tuser.class);
Criteria.add (Expression.eq ("name", "Erica"));
Session Session2 = getsession ();
Criteria criteria2 = Session2.createcriteria (Tuser.class);
Criteria2.add (Expression.eq ("name", "Erica"));
List userlist = Criteria.list ();
List userList2 = Criteria2.list (); TUser user = (TUser) userlist.get (0);
TUser user2 = (TUser) userlist2.get (0);
Transaction tx = Session.begintransaction ();
Transaction tx2 = Session2.begintransaction ();
User2.setusertype (99);
Tx2.commit ();
User.setusertype (1);
Tx.commit ();
Execute the above code, the code will be thrown at Tx.commit () staleobjectstateexception
The version check fails and the current transaction is attempting to submit an out-of-date data. By catching this anomaly, I
They can be handled when optimistic lock verification fails
Application scenarios for optimistic locking and pessimistic locking