Hibernate悲观锁与乐观锁及事宜管理机制

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 class="uuid"/>
		</id>
		<version name="version"/>
		<property name="name"/>
		<property name="password"/>
		<property name="createTime"/>
		<property name="expireTime"/>
	</class>
</hibernate-mapping>	

 

 

一样采用两个测试方法进行测试:

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]