Hibernate pessimistic lock/optimistic lock

Source: Internet
Author: User
Tags commit constructor flush

There is a data conflict between the default transactions, so the transaction is required to lock the data when the data is read and ensure the data access is exclusive;
The lock will be held by the transaction until the end of the transaction to release the lock.

one, pessimistic lock

The most common is to lock the query (Lockmode.upgrade and lockmode.upgrade_nowait), pessimistic lock can be implemented in the following three ways:

1) call Session.load () and set the Lockmode

2) call Session.lock ()

3) Call Query.setlockmode ()

Package edu.test;
Import Org.hibernate.LockMode;
Import org.hibernate.Session;
Import Org.hibernate.SessionFactory;
Import org.hibernate.Transaction;
Import Edu.po.Users;

Import Edu.utils.HibernateSessionFactory; /** * Title:PessimisticLockTest.java * Description: Pessimistic lock Test * @author Yh.zeng * @date 2017-6-27 * * public class Pessim
	
	isticlocktest {static Sessionfactory sessionfactory = Hibernatesessionfactory.getsessionfactory ();
		public static void Main (String args[]) {Session session = Sessionfactory.opensession ();
		
		Transaction Transaction = Session.begintransaction ();
			try {//mode one, use Session.load () to add pessimistic locks to data users user = (users) session.load (Users.class, 6, Lockmode.upgrade);
		System.out.println ("User name:" + user.getusername () + ", Password:" + User.getpassword ());
			/*//Mode two, use Session.lock () to add pessimistic locks to the users user = (users) session.load (Users.class, 6);
			Session.lock (user, lockmode.upgrade); */* *//mode three, use Query.setlockmode () to add pessimistic lock to data * String HQL = "from Users u where u.id =: id";
			Query query = session.createquery (HQL);
			Query.setparameter ("id", 6);
			Query.setlockmode ("U", Lockmode.upgrade);  
		    List<users> userlist = Query.list ();
		    For (users user:userlist) {System.out.println ("username:" + user.getusername () + ", Password:" + User.getpassword ());
		}*/Transaction.commit ();
			} catch (Exception e) {e.printstacktrace ();
		Transaction.rollback ();
		}finally{Session.close ();
 }
		
	}

}

Hibernate adds a FOR UPDATE clause after the generated SQL:

Hibernate:select users0_.id as id0_0_, users0_.version as version0_0_, users0_.username as username0_0_, Users0_.passwor D as password0_0_ from Test.users users0_ where users0_.id=? For update
user name: 32323, Password: bb

Hibernate provides 2 lock objects, Lockmode and lockoptions:

With the Lockoptions source code, you can find that lockoptions is just a simple package of lockmode (timeout and scope provided on lockmode basis):

......
/**
 * NONE represents Lockmode.none (timeout + scope do not apply)
 */public
static final lockoptions NONE = n EW lockoptions (lockmode.none);

/**
 * Read represents Lockmode.read (timeout + scope do not apply)
 */public
static final lockoptions READ = n EW lockoptions (lockmode.read);

/**
 * UPGRADE represents lockmode.upgrade (would wait forever for lock and
 * Scope of false meaning only entity is Locked)
 *
/public static final lockoptions UPGRADE = new Lockoptions (lockmode.upgrade);

Public lockoptions () {} public

lockoptions (Lockmode lockmode) {
	this.lockmode = Lockmode;
}
.....
public static final int no_wait = 0;

/**
 * Indicates that there are no timeout for the acquisition.
 * @see #getTimeOut
 *
/public static final int wait_forever =-1;

private int timeout = Wait_forever;

Private Boolean scope=false;
......

second, optimistic lock

Optimistic locks are mostly implemented based on the data versioning mechanism, which adds a version identifier to the data.

In general, add the version column in the database to record the versions of each row of data, and each time the object is updated, the value of the corresponding row's version field is incremented by one. In addition to using version as the Release ID, you can also use timestamp as the version ID.

CREATE TABLE users (
  ID int (one) not NULL auto_increment,
  username varchar (+) default NULL,
  password varchar (+) default NULL,
  version int (one) default null,
  PRIMARY KEY  (ID)
) engine=innodb  default CHARSET =utf8

Users.java:

package Edu.po; /** * Users entity. @author myeclipse Persistence Tools */public class Users implements java.io.Serializable {//Fields private Intege
	R ID;
	Private Integer version;
	Private String username;

	private String password;  Constructors/** Default constructor */public users () {}/** full constructor * * Public users (String username,
		String password) {this.username = username;
	This.password = password;
	}//Property accessors Public Integer getId () {return this.id;
	} public void SetId (Integer id) {this.id = ID;
	} public Integer GetVersion () {return this.version;
	} public void Setversion (Integer version) {this.version = version;
	} public String GetUserName () {return this.username;
	} public void Setusername (String username) {this.username = username;
	} public String GetPassword () {return this.password;
	} public void SetPassword (String password) {this.password = password; }

}


Users.hbm.xml:

<?xml version= "1.0" encoding= "Utf-8"?> <! DOCTYPE hibernate-mapping Public "-//hibernate/hibernate mapping DTD 3.0//en" "http://hibernate.sourceforge.net/ Hibernate-mapping-3.0.dtd "> <!--mapping file autogenerated by MyEclipse persistence Tools---Package edu.test;
Import org.hibernate.Session;
Import Org.hibernate.SessionFactory;
Import org.hibernate.Transaction;
Import Edu.po.Users;

Import Edu.utils.HibernateSessionFactory; /** * Title:OptimisticTest.java * description:hibernate optimistic Lock Test * @author Yh.zeng * @date 2017-6-27 */public class Op
	
	timistictest {static Sessionfactory sessionfactory = Hibernatesessionfactory.getsessionfactory ();

		public static void Main (String args[]) {Session session1 = sessionfactory.opensession ();
		
		Session Session2 = Sessionfactory.opensession ();
			try {Users User1 = (users) session1.get (Users.class, 6);
			
			Users user2 = (users) session2.get (Users.class, 6);
			
			System.out.println ("User1 version=" +user1.getversion () + "," + "User2 version=" +user2.getversion ());
			Transaction Transaction1 = Session1.begintransaction ();
			
			Transaction Transaction2 = Session2.begintransaction ();
			User1.setpassword ("11");
			
			Transaction1.commit (); System.out.println ("User1 of version= "+user1.getversion () +", "+" User2 version= "+user2.getversion ());
			User2.setpassword ("111111");
			
		Transaction2.commit ();
		} catch (Exception e) {e.printstacktrace ();
			}finally{Session1.close ();
		Session2.close ();
 }
		
	}

}

The


runs as follows, and you can see that the version field has been modified since Transaction1 was submitted. Transaction2 throws a Org.hibernate.StaleObjectStateException exception when committed:

Hibernate:select users0_.id as id0_0_, users0_.version as version0_0_, users0_.username as username0_0_, Users0_.passwor
D as password0_0_ from Test.users users0_ where users0_.id=? Hibernate:select users0_.id as id0_0_, users0_.version as version0_0_, users0_.username as username0_0_, Users0_.passwor
D as password0_0_ from Test.users users0_ where users0_.id=? User1 version=17,user2 version=17 hibernate:update test.users set version=?, Username=?, password=? where id=?
and version=? User1 version=18,user2 version=17 hibernate:update test.users set version=?, Username=?, password=? where id=?
and version=? 2017-7-3 21:59:03 org.hibernate.event.def.AbstractFlushingEventListener performexecutions severity: Could not synchronize  Database state with session Org.hibernate.StaleObjectStateException:Row is updated or deleted by another transaction (or Unsaved-value mapping was incorrect): [Edu.po.users#6] at Org.hibernate.persister.entity.AbstractEntityPersister.check (ABSTRACTENTITYPERSISTER.Java:1782) at Org.hibernate.persister.entity.AbstractEntityPersister.update (abstractentitypersister.java:2425) at Org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert (abstractentitypersister.java:2325) at Org.hibernate.persister.entity.AbstractEntityPersister.update (abstractentitypersister.java:2625) at Org.hibernate.action.EntityUpdateAction.execute (entityupdateaction.java:115) at Org.hibernate.engine.ActionQueue.execute (actionqueue.java:279) at Org.hibernate.engine.ActionQueue.executeActions (actionqueue.java:263) at Org.hibernate.engine.ActionQueue.executeActions (actionqueue.java:168) at Org.hibernate.event.def.AbstractFlushingEventListener.performExecutions (abstractflushingeventlistener.java:321 ) at Org.hibernate.event.def.DefaultFlushEventListener.onFlush (DEFAULTFLUSHEVENTLISTENER.JAVA:50) at Org.hibernate.impl.SessionImpl.flush (sessionimpl.java:1028) at Org.hibernate.impl.SessionImpl.managedFlush ( sessionimpl.java:366) at Org.hibernate.transaction.JDBCTrAnsaction.commit (jdbctransaction.java:137) at Edu.test.OptimisticTest.main (optimistictest.java:42) Org.hibernate.StaleObjectStateException:Row was updated or deleted by another transaction (or Unsaved-value mapping was I Ncorrect): [Edu.po.users#6] at Org.hibernate.persister.entity.AbstractEntityPersister.check ( abstractentitypersister.java:1782) at Org.hibernate.persister.entity.AbstractEntityPersister.update ( abstractentitypersister.java:2425) at Org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert ( abstractentitypersister.java:2325) at Org.hibernate.persister.entity.AbstractEntityPersister.update ( abstractentitypersister.java:2625) at Org.hibernate.action.EntityUpdateAction.execute (Entityupdateaction.java : +) at Org.hibernate.engine.ActionQueue.execute (actionqueue.java:279) at Org.hibernate.engine.ActionQueue.executeActions (actionqueue.java:263) at Org.hibernate.engine.ActionQueue.executeActions (actionqueue.java:168) at Org.hibernate.event.def.AbstractFlushinGeventlistener.performexecutions (abstractflushingeventlistener.java:321) at Org.hibernate.event.def.DefaultFlushEventListener.onFlush (DEFAULTFLUSHEVENTLISTENER.JAVA:50) at Org.hibernate.impl.SessionImpl.flush (sessionimpl.java:1028) at Org.hibernate.impl.SessionImpl.managedFlush ( sessionimpl.java:366) at Org.hibernate.transaction.JDBCTransaction.commit (jdbctransaction.java:137) at Edu.test.OptimisticTest.main (optimistictest.java:42)


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.