The role of optimistic locking
The main function of optimistic lock is to solve the problem caused by transaction concurrency. In contrast to pessimistic lock, the optimistic locking mechanism adopts a more relaxed locking mechanism.
Pessimistic lock in most cases rely on the database lock mechanism to achieve the maximum degree of exclusivity to ensure the operation. But then comes the massive cost of database performance, especially for long transactions, which are often unsustainable. The optimistic locking mechanism solves this problem to some extent. Optimistic locks, most of which are based on data Versioning (version) recording mechanism implementations. What is the data version. That is, adding a version identity to the data, in a version solution based on a database table, typically by adding a "version" field to the database table.
The working principle of optimistic lock
When you read out the data, read the version number together, and then when you update it, add one to this version number. At this point, the version data for the submitted data is compared to the current version information of the corresponding record in the database table, and is updated if the submitted data version number is greater than the current version number of the database table, otherwise it is considered to be an expired data.
Optimistic lock implementation based on Hibernate
Optimistic lock implementation based on hibernate generally has the following two kinds of methods
Based on timestamp based on version
Here's an introduction to optimistic lock implementation based on version
XML code
<?xmlVersion= "1.0"
?><! DOCTYPE hibernate-mapping Public "-//hibernate/hibernate mapping DTD 3.0//en" "Http://hibernate.source Forge.net/hibernate-mapping-3.0.dtd "
>
<className= "Test. Dir "table=" T_dir " > <idName= "id" type= "string" unsaved-value= "null" > <columnName= "Id_" sql-type= "char" not-null= "true" /> <generatorClass= "Uuid.hex" /> </id> <versionColumn= "Version_" name= "version" /> <propertyName= "name" column= "Name_" type= "string" /> <propertyName= "Size" column= "Size_" type= "Long" /> <many-to-oneName= "dir" column= "pid_" class= "test." Dir " /> </class> <?xml version= "1.0"?>
<! DOCTYPE hibernate-mapping public
"-//hibernate/hibernate mapping DTD 3.0//en"
"http:// Hibernate.sourceforge.net/hibernate-mapping-3.0.dtd ">
Note here that the version's position must be placed behind the ID
Problems caused by optimistic locks
When two different transactions are read and modified at the same time, the program throws Org.hibernate.StaleObjectStateException:Row is updated or deleted by another Transaction (or Unsaved-value mapping was incorrect) exception.
There are two things here, too.
One is the case of two different transactions
Java code @Test public void testtransation1 () { session session1 = null; Session session2 = null; try{ Session1 = hibernateutil.getsession (); Session2 = hibernateutil.getsession (); dir dir1 = (Dir) session1.load (dir.class, "4028811a3d3387d3013d3387d4a40008"); Dir dir2 = (Dir) session2.load (dir.class, " 4028811a3d3387d3013d3387d4a40008 "); transaction tx1 = session1.begintransaction (); Dir1.setsize (1111); tx1.commit (); transaction tx2 = session2.begintransaction (); dir2.setsize (999); tx2.commit (); system.out.println ("Transaction 2 commit "); }catch (exception e) { e.printstacktrace (); }finally{ if (session1 != null) { session1.close (); } if (session2 != null) { &NBSP;&NBSP; session2.close (); } } }
@Test public
void TestTransation1 () {session
session1 = null;
Session session2 = NULL;
try{
session1 = hibernateutil.getsession ();
Session2 = Hibernateutil.getsession ();
Dir dir1 = (dir) session1.load (Dir.class, "4028811a3d3387d3013d3387d4a40008");
Dir dir2 = (dir) session2.load (Dir.class, "4028811a3d3387d3013d3387d4a40008");
Transaction tx1 = Session1.begintransaction ();
Dir1.setsize (1111);
Tx1.commit ();
Transaction tx2 = Session2.begintransaction ();
Dir2.setsize (999);
Tx2.commit ();
System.out.println ("Transaction 2 Commit");
} catch (Exception e) {
e.printstacktrace ();
} finally{
if (session1!= null) {
session1.close ();
}
if (session2!= null) {
session2.close ();}}}
Transaction 2 When the value of version is found to be different, this time it throws Org.hibernate.StaleObjectStateException:Row is updated or deleted by another Transaction (or Unsaved-value mapping was incorrect) exception
The second case is the case of a child transaction
Java code @Test public void testtransation5 () { session session1 = null; Session session2 = null; try{ Session1 = hibernateutil.getsession (); Session2 = hibernateutil.getsession (); dir dir1 = (Dir) session1.load (dir.class, "4028811a3d3387d3013d3387d4a40008"); Dir dir2 = (Dir) session2.load (dir.class, " 4028811a3d3387d3013d3387d4a40008 "); transaction tx1 = session1.begintransaction (); transaction Tx2 = session2.begintransaction (); Dir2.setsize (7777); tx2.commit (); dir1.setsize (3333); tx1.commit (); }catch (exception e) { e.printstacktrace (); }finally{ if (session1 != null) { session1.close (); } if (session2 != null) { session2.close (); &nbSp } } }
@Test public
void TestTransation5 () {session
session1 = null;
Session session2 = NULL;
try{
session1 = hibernateutil.getsession ();
Session2 = Hibernateutil.getsession ();
Dir dir1 = (dir) session1.load (Dir.class, "4028811a3d3387d3013d3387d4a40008");
Dir dir2 = (dir) session2.load (Dir.class, "4028811a3d3387d3013d3387d4a40008");
Transaction tx1 = Session1.begintransaction ();
Transaction tx2 = Session2.begintransaction ();
Dir2.setsize (7777);
Tx2.commit ();
Dir1.setsize (3333);
Tx1.commit ();
} catch (Exception e) {
e.printstacktrace ();
} finally{
if (session1!= null) {
session1.close ();
}
if (session2!= null) {
session2.close ();}}}
We found that 2 of things are wrapped in transaction 1, if DIR is configured to delay loading (hibnernate default is delayed loading), this time when the transaction 1 commits, will go to the database to query, and then update operations.
If DIR is configured to not delay loading (lazy= "false"), then transaction 1 does not query the database at the time of submission, but submits it directly and finds version mismatch at the time of submission. It will also throw Org.hibernate.StaleObjectStateException:Row is updated or deleted by another transaction (or Unsaved-value Mappin G was incorrect) exception
Solutions
1, Catch staleobjectstateexception exception, prompted the data obsolete has been modified to allow users to resubmit
2, as far as possible from the business to reduce transaction block, the larger the transaction block, by the optimistic lock caused by the greater the probability of the problem