`

hibernate学习13之悲观锁与乐观锁

阅读更多
悲观锁Pessimistic

悲观锁的实现,通常依赖于数据库机制,在整个过程中将数据锁定,其它任何用户都不能读取或修改
一旦使用了悲观锁,load的lazy会失效
看下面的例子:
import org.hibernate.LockMode;
import org.hibernate.Session;

import junit.framework.TestCase;

public class PessimisticLockingTest extends TestCase {

//如果第一个人执行这个方法,执行到一半,然后走了
	public void testLoad1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();
			
			Inventory inv = (Inventory)session.load(Inventory.class, 1, LockMode.UPGRADE);//锁住,不让别人操作
			System.out.println("itemName=" + inv.getItemName());
			System.out.println("quantity=" + inv.getQuantity());
			inv.setQuantity(inv.getQuantity() - 200);
			session.update(inv);
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
//第二个人不能加载数据了,堵塞住了(一直等待),只有当第一个用户释放了,代码才能继续执行下去。
	public void testLoad2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();
			
			Inventory inv = (Inventory)session.load(Inventory.class, 1, LockMode.UPGRADE);
			System.out.println("itemName=" + inv.getItemName());
			System.out.println("quantity=" + inv.getQuantity());
			inv.setQuantity(inv.getQuantity() - 200);
			session.update(inv);
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
}



乐观锁optimistic

原理:大多数基于数据版本记录机制(version)实现,一般是在数据库表中加入一个version字段
读取数据时将版本号一同读出,之后更新数据时版本号加一,如果提交数据时版本号小于或等于数据表中的版本号,则认为数据是过期的,否则给予更新
public class Inventory {
	private int itemNo;	
	private String itemName;	
	private int quantity;	
	private int version;//新增版本字段,用户检测数据是否是最新的。
	//setter,getter	
}


乐观锁配置:
<?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.Inventory" table="t_inventory" optimistic-lock="version">
		<id name="itemNo">
			<generator class="native"/>
		</id>
<!--version必须配置在主键后面-->
		<version name="version"/>
		<property name="itemName"/>
		<property name="quantity"/>
	</class>
</hibernate-mapping>


乐观锁测试一下:
import org.hibernate.LockMode;
import org.hibernate.Session;

import junit.framework.TestCase;

public class OptimisticLockingTest extends TestCase {
//如果第一个人先执行这个方法,执行到一半,然后走了
	public void testLoad1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();
			
			Inventory inv = (Inventory)session.load(Inventory.class, 1);
			System.out.println("itemName=" + inv.getItemName());
			System.out.println("version=" + inv.getVersion());
			System.out.println("quantity=" + inv.getQuantity());
			inv.setQuantity(inv.getQuantity() - 200);
			session.update(inv);
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
//这个时候第二个人执行这个方法,并且执行完毕;然后第一个人回来了,继续执行第一个方法会发现异常,因为数据库内部对比了版本号发现不对,所以抛异常了。(数据过期)
	public void testLoad2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();
			
			Inventory inv = (Inventory)session.load(Inventory.class, 1);
			System.out.println("itemName=" + inv.getItemName());
			System.out.println("version=" + inv.getVersion());
			System.out.println("quantity=" + inv.getQuantity());
			inv.setQuantity(inv.getQuantity() - 200);
			session.update(inv);
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics