使用一个线程安全的Session:SessionFactory.getCurrentSession()
需要配置Hibernate.cfg.xml 属性current_session_context_class = thread
从数据库获取数据时,要加锁session.get(SomeClass.Class,id,LockMode.UPGRADE)
试了一晚上,用Mysql做的测试,居然不行...下面的代码仅在Oracle下测试通过
实体类
public class Book {
private int bid;
private String name;
private boolean borrow = false;
private String owner;
} //省略无参构造函数和getter/setter
borrow布尔类型变量用于标识书是否被借出
owner 用于标识当前拥有者
测试线程类(测试多线程并发访问情况下悲观锁的效果)
public class Student extends Thread {
private int bookid;
private String stdname;
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, LockMode.UPGRADE);
if(book.isBorrow()){ //书已经借出的情况返回false
System.out.println("isborrow_false");
return false;
}
book.setBorrow(true);
book.setOwner(this.stdname);
ss.save(book);
ts.commit();
return true; //借书成功,返回true
}catch(Exception e){
ts.rollback();
e.printStackTrace();
System.out.println("Exception_false");
return false; //出错的时候返回false
}finally{
ss.close();
}
}
}
Hibernate 配置文件 <property name="current_session_context_class">thread</property>
产生Session的工具类
public class DBFactory {
public static SessionFactory sf = null;
static{
sf = new Configuration().configure().buildSessionFactory();
}
public static Session getSession(){
return sf.getCurrentSession(); //注意,此处返回的是线程安全的currentSession
}
}
测试类
public class Test {
public static void main(String[] args) {
// addBook(); //用于构造books表的方法调用
Student lixun = new Student("Lixun",1); //开启两个独立线程去借书
lixun.start();
Student zhougege = new Student("zhougege",1);
zhougege.start();
}
public static void addBook(){ //用于构造books表的方法
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();
}
}
}