Hibernate乐观锁实现方式

hibernate乐观锁

,Student.java

package com.fgh.hibernate;

import java.sql.Timestamp;

public class Student {

	private String id;

	private String name;

	private int age;

	private String cardId;

	// private Timestamp lastDate;

	private int version;

	public int getVersion() {
		return version;
	}

	public void setVersion(int version) {
		this.version = version;
	}

	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 int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getCardId() {
		return cardId;
	}

	public void setCardId(String cardId) {
		this.cardId = cardId;
	}

	// public Timestamp getLastDate() {
	// return lastDate;
	// }
	//
	// public void setLastDate(Timestamp lastDate) {
	// this.lastDate = lastDate;
	// }

}

Student.hbm.xml

<?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.fgh.hibernate.Student"
		table="student_optimistic">
		<id name="id" column="id" type="string">
			<generator class="uuid"></generator>

		</id>
		<!-- 这个位置要放在property之前 timestamp和version本质上是一样的 -->
		<!-- <timestamp name="timestamp" column="lastDate"></timestamp> -->
		<version name="version" column="version" type="integer"></version>
		<property name="name" column="name" type="string"></property>
		<property name="cardId" column="cardId" type="string"></property>
		<property name="age" column="age" type="integer"></property>
	</class>

</hibernate-mapping>

测试类HibernateTest.java

package com.fgh.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 e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {

		// 生成两个session 模拟双线程并发
		Session session1 = sessionFactory.openSession();
		Session session2 = sessionFactory.openSession();
		//Transaction tx = null;
		Transaction tx1 = null;
		Transaction tx2 = null;

		try {
			/**保存操作
			 tx = session.beginTransaction();
			 Student student = new Student();
			 student.setAge(20);
			 student.setCardId("123");
			 student.setName("zhangsan");
			 session.save(student);
			 tx.commit();
			*/
			// 使用HQL查询 :name叫命名参数 調用setString方法为参数设值
			// 然后调用uniqueResult方法返回唯一的对象
			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());

			// 线程1 修改了name属性 然后提交事务 单独执行 线程1
			// 打印出student2的version为0 因为线程2事务还没有提交
			tx1 = session1.beginTransaction();
			student1.setName("lisi");
			tx1.commit();
			System.out.println(student1.getVersion());
			System.out.println(student2.getVersion());

			// 线程2 同样修改了name属性 但是在此之前 已经对name属性做了修改
			// 查询的时候name已更新为lisi 所以该处会抛异常StaleObjectStateException
			//student1 version=1  student2 version=0
			tx2 = session2.beginTransaction();
			student2.setName("wangwu");
			tx2.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (null != tx1) {
				tx1.rollback();
			} else if (null != tx2) {
				tx2.rollback();
			}
		} finally {
			session1.close();
			session2.close();
		}
	}
}

整体执行结果:

Hibernate: select student0_.id as id0_, student0_.version as version0_, student0_.name as name0_, student0_.cardId as cardId0_, student0_.age as age0_ from student_optimistic student0_ where student0_.name=?
Hibernate: select student0_.id as id0_, student0_.version as version0_, student0_.name as name0_, student0_.cardId as cardId0_, student0_.age as age0_ from student_optimistic student0_ where student0_.name=?
0
0
Hibernate: update student_optimistic set version=?, name=?, cardId=?, age=? where id=? and version=?
1
0
Hibernate: update student_optimistic set version=?, name=?, cardId=?, age=? where id=? and version=?
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.fgh.hibernate.Student#8a8ae4d934d2705b0134d2705cfb0001]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1765)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2407)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2307)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2607)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at com.fgh.hibernate.HibernateTest.main(HibernateTest.java:56)
Exception in thread "main" org.hibernate.TransactionException: Transaction not successfully started
at org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:149)
at com.fgh.hibernate.HibernateTest.main(HibernateTest.java:63)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值