乐观锁(Optimistic Lock)之version(版本号)与timestamp(时间戳)配置解读

version(版本号)

版本号配置中须指明  optimistic-lock="version"

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    <class name="com.hibernate.Student" table="student" optimistic-lock="version">
    	<id name="id" column="id" type="string"> 
    		<generator class="uuid"></generator>
    	</id>
    	
    	<version name="version" column="version" type="integer"></version>
    	
    	<property name="cardId" column="cardId" type="string"></property>
    	<property name="age" column="age" type="integer"></property>
    	<property name="name" column="name" type="string"></property>
    	
    </class>
    </hibernate-mapping>

在测试类HibernateTest中session1会话查询修改student表后, 如果session2会话中再对student表进行修改,此时会抛出org.hibernate.StaleObjectStateException异常,意思是说第一次修改后表中version的值会由0变为1(表中version的初始值为0),当第二次尝试进行修改的时候底层会将查询时获得version(值为0)与数据库中一更新的值为1的version进行对比,发现0 < 1 便会抛出以上异常(大概是过期的类状态异常的意思)。

HibernateTest类代码如下:

package com.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class HibernateTest {
	private static SessionFactory sessionFactory;
	static
	{
		try
		{
			sessionFactory = new Configuration().configure().buildSessionFactory();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	public static void main(String[] args) {
		
		
		Session session = sessionFactory.openSession();
		Transaction tx  = null;
		try
		{
			tx = session.beginTransaction();
//			Student student = new Student();
//			student.setName("zhangsan");
//			student.setAge(20);
//			student.setCardId("14");
//			session.save(student);
//			tx.commit();
			
			Session session1 = sessionFactory.openSession();
			Session session2 = sessionFactory.openSession();
			
			Student student1 = (Student)session1.createQuery("from Student s where s.name = :name").setString("name", "zhangsan").uniqueResult();
			Student student2 = (Student)session2.createQuery("from Student s where s.name = :name").setString("name", "zhangsan").uniqueResult();
			
			System.out.println(student1.getVersion());
			System.out.println(student2.getVersion());
			
			Transaction tx1 = session1.beginTransaction();
			student1.setName("lisi");
			tx1.commit();
			
			System.out.println(student1.getVersion());
			System.out.println(student2.getVersion());
			
			Transaction tx2 = session2.beginTransaction();
			student2.setCardId("111");
			tx2.commit();
			
			System.out.println(student1.getVersion());
			System.out.println(student2.getVersion());
			
			
			
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
			if(null != tx)
			{
				tx.rollback();
			}
		}
		finally
		{
			session.close();
		}
		
	}

}
对应的控制台的输出信息如下:

Hibernate: 
    select
        student0_.id as id0_,
        student0_.version as version0_,
        student0_.cardId as cardId0_,
        student0_.age as age0_,
        student0_.name as name0_ 
    from
        student student0_ 
    where
        student0_.name=?
Hibernate: 
    select
        student0_.id as id0_,
        student0_.version as version0_,
        student0_.cardId as cardId0_,
        student0_.age as age0_,
        student0_.name as name0_ 
    from
        student student0_ 
    where
        student0_.name=?
0
0
Hibernate: 
    update
        student 
    set
        version=?,
        cardId=?,
        age=?,
        name=? 
    where
        id=? 
        and version=?
1
0
Hibernate: 
    update
        student 
    set
        version=?,
        cardId=?,
        age=?,
        name=? 
    where
        id=? 
        and version=?
<span style="color:#ff0000;">org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.hibernate.Student#ef3262e84974c56c014974c56dc60000]</span>



timestamp(时间戳)

时间戳配置中无须指明optimistic-lock参数

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    <class name="com.hibernate.Student" table="student">
    	<id name="id" column="id" type="string"> 
    		<generator class="uuid"></generator>
    	</id>
    	
    	<timestamp name="lastDate" column="lastDate"></timestamp>
    	<property name="cardId" column="cardId" type="string"></property>
    	<property name="age" column="age" type="integer"></property>
    	<property name="name" column="name" type="string"></property>
    	
    </class>
    </hibernate-mapping>
对于timestamp的测试方法与version原理方法基本一样,大家可以自己尝试一下,谢谢!

展开阅读全文

没有更多推荐了,返回首页