Hibernate悲观锁与乐观锁及事务管理机制
引用:
悲观锁与乐观锁:
http://www.iteye.com/topic/179267
http://hi.baidu.com/ahuzl/blog/item/1340fe8307dc16b56d81194b.html
事务管理机制:
http://www.router.net.cn/Article/26494.html
http://www.iteye.com/topic/280746
?
悲观锁示例:
POJO 为User类
在示例中从数据库load出来,分别用两个测试方法来,在第一个方法里面设置断点,会发现直到第一个方法执行完,第二个方法才进行更新。
说明锁定的情况下其它session不能更新。
package com.bjsxt.hibernate;import junit.framework.TestCase;import org.hibernate.LockMode;import org.hibernate.Session;public class PessimisticLockingTest extends TestCase {public void testUpdate1() {Session session = null;try {session = HibernateUtils.getSession();session.beginTransaction();User user = (User)session.load(User.class, "402880f6286c790b01286c7911eb0001", LockMode.UPGRADE);System.out.println("name=" + user.getName());System.out.println("password=" + user.getPassword());user.setPassword("a");session.update(user);session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}public void testUpdate2() {Session session = null;try {session = HibernateUtils.getSession();session.beginTransaction();User user = (User)session.load(User.class, "402880f6286c790b01286c7911eb0001", LockMode.UPGRADE);System.out.println("name=" + user.getName());System.out.println("password=" + user.getPassword());user.setPassword("b");session.update(user);session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}}
?
?
乐观锁:
在User类里面增加属性version
package com.bjsxt.hibernate;import java.util.Date;public class User {private String id;private String name;private String password;private Date createTime;private Date expireTime;//采用乐观锁,进行并发控制private int version;public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public Date getExpireTime() {return expireTime;}public void setExpireTime(Date expireTime) {this.expireTime = expireTime;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public int getVersion() {return version;}public void setVersion(int version) {this.version = version;}}
?
配置文件:
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.bjsxt.hibernate.User" optimistic-lock="version"><id name="id"><generator name="code">package com.bjsxt.hibernate;import java.util.Date;import org.hibernate.LockMode;import org.hibernate.Session;import junit.framework.TestCase;public class OptimisticLockingTest extends TestCase {public void testUpdate1() {Session session = null;try {session = HibernateUtils.getSession();session.beginTransaction();User user = (User)session.load(User.class, "402880f6286c93c101286c93c7130001");System.out.println("name=" + user.getName());System.out.println("password=" + user.getPassword());user.setPassword("a");session.update(user);session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}public void testUpdate2() {Session session = null;try {session = HibernateUtils.getSession();session.beginTransaction();User user = (User)session.load(User.class, "402880f6286c93c101286c93c7130001");System.out.println("name=" + user.getName());System.out.println("password=" + user.getPassword());System.out.println("version=" + user.getVersion());user.setPassword("b");session.update(user);session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}}
?
可在第一个方法中设置断点,debug,而第二个方法run。看看执行的情况。
乐观锁User的表
+------------+--------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+------------+--------------+------+-----+---------+-------+| id | varchar(255) | NO | PRI | NULL | || version | int(11) | NO | | NULL | || name | varchar(255) | YES | | NULL | || password | varchar(255) | YES | | NULL | || createTime | datetime | YES | | NULL | || expireTime | datetime | YES | | NULL | |+------------+--------------+------+-----+---------+-------+
?
虽然加了version字段,但是不需要设置该属性值,如下:
package com.bjsxt.hibernate;import java.util.Date;import org.hibernate.Session;public class InitData {public static void main(String[] args) {Session session = null;User user = new User();try {session = HibernateUtils.getSession();session.beginTransaction();user.setName("张三");user.setPassword("123");user.setCreateTime(new Date());user.setExpireTime(new Date());session.save(user);session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}}
?
?
我在测试方法一中的System.out.println("name=" + user.getName());处设置断点,然后执行debug这个方法。
执行到断点处,我们发现从数据库查询出来的version=0,这时再执行测试方法二,会发现测试方法二立刻执行,并把version变成为1,测试方法二执行完,我们再按F6下一步时,测试方法一执行到commit的时候会抛出异常:
这是因为乐观锁发现自身的version<=数据库中的version的时候更新不了。。
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.bjsxt.hibernate.User#402880f6286c93c101286c93c7130001]
?