使用一个线程安全的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(); } } }