hibernate---->悲观锁和乐观锁

一、悲观锁

悲观锁的实现,通常依赖于数据库机制,在整个过程中将数据锁定,其它任何用户都不能读取或修改

悲观锁的实现:

显式的用户指定"可以通过以下几种方式之一来表示:

  • 调用 Session.load()的时候指定锁定模式(LockMode)

  • 调用Session.lock()

  • 调用Query.setLockMode()

package com.wsz.test;

import junit.framework.TestCase;

import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.wsz.entity.HibernateUtils;
import com.wsz.entity.Products;

public class Test extends TestCase {

	public void testSave() {
		Session session = null;
		Transaction tx = null;
		Products products = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();
            products=new Products();
            products.setName("脑白金");
            products.setTotalnumber(1000);
            session.save(products);
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		} finally {
			HibernateUtils.closeSession(session);
		}

	}

	public void test1() {

		Products products = new Products();
		Session session = HibernateUtils.getSession();
		session.beginTransaction();
		//悲观锁的实现
		products = (Products) session.load(products.getClass(), 1,LockMode.UPGRADE);
		System.out.print(products.getName());
		System.out.println(products.getTotalnumber());
		products.setTotalnumber(products.getTotalnumber()-200);
		session.getTransaction().commit();

	}
	
	
	public void test2() {

		Products products = new Products();
		Session session = HibernateUtils.getSession();
		session.beginTransaction();
		products = (Products) session.load(products.getClass(), 1,LockMode.UPGRADE);
		System.out.print(products.getName());
		System.out.println(products.getTotalnumber());
		products.setTotalnumber(products.getTotalnumber()-200);
		session.getTransaction().commit();

	}

}

使用悲观锁,lazy属性失效,立即发出sql。

二、乐观锁

大多数基于数据版本记录机制(version)实现,一般是在数据库表中加入一个version字段,读取数据时将版本号一同读出,之后更新数据时版本号加一,如果提交数据时版本号小于或等于数据表中的版本号,则认为数据是过期的,否则给予更新。

Products.hbm.xml

<hibernate-mapping>
	<class name="com.wsz.entity.Products" table="t_products" optimistic-lock="version">
		<id name="id">
			<generator class="native" />
		</id>
		<version name="version"/>
		<property name="name" />
		<property name="totalnumber" />
	</class>
</hibernate-mapping>

数据库表多了一个version字段

开始version=0

如果更新后 version=1,由数据库自动更新。

Products.java

package com.wsz.entity;


public class Products {
	private int id;
	private String name;
	private int  totalnumber;
	private int version;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getTotalnumber() {
		return totalnumber;
	}
	public void setTotalnumber(int totalnumber) {
		this.totalnumber = totalnumber;
	}
	public int getVersion() {
		return version;
	}
	public void setVersion(int version) {
		this.version = version;
	}
	



}

Test.java

package com.wsz.test;

import junit.framework.TestCase;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.wsz.entity.HibernateUtils;
import com.wsz.entity.Products;

public class Test extends TestCase {

	public void testSave() {
		Session session = null;
		Transaction tx = null;
		Products products = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();
            products=new Products();
            products.setName("naobaijin");
            products.setTotalnumber(1000);
            session.save(products);
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		} finally {
			HibernateUtils.closeSession(session);
		}

	}

	public void test1() {

		Products products = new Products();
		Session session = HibernateUtils.getSession();
		session.beginTransaction();
		//悲观锁的实现
		products = (Products) session.load(products.getClass(), 1);
		System.out.print(products.getName());
		System.out.println(products.getTotalnumber());
		products.setTotalnumber(products.getTotalnumber()-200);
		session.getTransaction().commit();

	}
	
	
	public void test2() {

		Products products = new Products();
		Session session = HibernateUtils.getSession();
		session.beginTransaction();
		products = (Products) session.load(products.getClass(), 1);
		System.out.print(products.getName());
		System.out.println(products.getTotalnumber());
		products.setTotalnumber(products.getTotalnumber()-200);
		session.getTransaction().commit();

	}

}

使用悲观锁,lazy不会失效,不会立即发出sql

更新时发出的sql语句Hibernate: update t_products set version=?, name=?, totalnumber=? where id=? and version=?,

如果test1更新了,在commit设置断点,没有提交,test2更新了。此时test1往下运行,当前的version 小于数据库的version ,会生成如下的异常。

10:48:59,260 ERROR AbstractFlushingEventListener:301 - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.wsz.entity.Products#1]
 at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1699) 


 

 

posted on 2012-09-06 10:31  小强斋太  阅读(204)  评论(0编辑  收藏  举报

导航