实体类添加额外的属性version,映射文件中采用属性version 类似于版本控制系统(svn/cvs)的机制
并发冲突时会抛出StableObjectStateException
实体类
public class Book {
private int bid;
private String name;
private String owner;
private int version;
} //省略无参构造函数和getter/setter
测试线程类(测试多线程并发访问情况下悲观锁的效果)
public class Student extends Thread {
private int bookid;
private String stdname;
public boolean flag = false;
public Student(String name,int bookid){
this.bookid = bookid;
this.stdname = name;
}
public void run(){
if(this.borrowBook()){
System.out.println(this.stdname + "借书 成功!!!");
}else{
System.out.println(this.stdname + "借书 失败!!!");
}
}
public boolean borrowBook(){
Session ss = null;
Transaction ts = null;
Book book = null;
try{
ss = DBFactory.sf.openSession();
ts = ss.beginTransaction();
book = (Book) ss.get(Book.class,bookid);
book.setOwner(this.stdname);
ss.save(book);
ts.commit();
return true;
}catch(Exception e){
ts.rollback();
e.printStackTrace();
System.out.println("Exception_false");
return false;
}finally{
ss.close();
}
}
}
映射文件
<hibernate-mapping package="optimistic.entity"> <class name="Book" table="opti_book"> <id column="bookid" name="bid"> <generator class="native"/> </id> <version name="version" column="version"></version> <!--此处添加--> <property column="bookname" name="name" type="string"/> <property column="owner" name="owner" type="string"/> </class> </hibernate-mapping>
测试类
public class Test {
public static void main(String[] args) {
// addBook();
Student lixun = new Student("Lixun",1);
lixun.start();
Student zhougege = new Student("zhougege",1);
zhougege.start();
}
public static void addBook(){
Book book = new Book();
book.setName("**Mei");
Session ss = null;
Transaction ts = null;
try{
ss = DBFactory.sf.openSession();
ts = ss.beginTransaction();
ss.save(book);
ts.commit();
ss.close();
}catch(Exception e){
ts.rollback();
e.printStackTrace();
}
}
}
产生的异常:
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [optimistic.entity.Book#1]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1714)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2357)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2257)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2557)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)