您的位置:首页 > 其它

Hibernate乐观锁实现方式

2012-01-12 23:42 337 查看


,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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: