快速掌握Hibernate中悲观锁和乐观锁

 

快速掌握Hibernate中悲观锁和乐观锁

2009-09-25 16:43 佚名 blogjava  我要评论(0 )  字号: T  |  T
一键收藏,随时查看,分享好友!

Hibernate悲观锁:在数据有加载的时候就给其进行加锁,直到该锁被释放掉,其他用户才可以进行修改;Hibernate乐观锁:在对数据进行修改的时候,对数据才去版本或者时间戳等方式来比较,数据是否一致性来实现加锁。

AD: 51CTO云计算架构师峰会 抢票进行中!

 

我们在使用Hibernate中经常用到当多个人对同一数据同时进行修改的时候,会发生脏数据,造成数据的不一致性,解决办法是可以通过悲观锁和乐观锁来实现。

Hibernate悲观锁:在数据有加载的时候就给其进行加锁,直到该锁被释放掉,其他用户才可以进行修改,优点:数据的一致性保持得很好,缺点:不适合多个用户并发访问。当一个锁住的资源不被释放掉的时候,这个资源永远不会被其他用户进行修改,容易造成无限期的等待。(加载数据)

Hibernate乐观锁:就是在对数据进行修改的时候,对数据才去版本或者时间戳等方式来比较,数据是否一致性来实现加锁。优点比较好。(更改或者插入数据)

一、在Hibernate悲观锁中,只要在加载的时候,才去session中的load方法,进行枷锁,session.load(****.class,1,LockMode.UPDATE);

Hibernate将事务管理委托给底层的JDBC或者JTA,默认是基于JDBC Transaction的。Hibernate支持“悲观锁(Pessimistic Locking)”和“乐观锁(Optimistic Locking)”。
Hibernate悲观锁对数据被外界修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。Hibernate悲观锁的实现,往往依靠数据库提供的锁机制。Hibernate通过使用数据库的for update子句实现了悲观锁机制。

Hibernate的加锁模式有:

1. LockMode.NONE:无锁机制

2. LockMode.WRITE:Hibernate在Insert和Update记录的时候会自动获取

3. LockMode.READ:Hibernate在读取记录的时候会自动获取

4. LockMode.UPGRADE:利用数据库的for update子句加锁

5. LockMode.UPGRADE_NOWAIT:Oracle的特定实现,利用Oracle的for update nowait子句实现加锁


二、乐观锁大多是基于数据版本(Version)记录机制实现。Hibernate在其数据访问引擎中内置了Hibernate乐观锁实现,可以通过class描述符的optimistic-lock属性结合version描述符指定。optimistic-lock属性有如下可选取值:


1. none:无乐观锁

2. version:通过版本机制实现乐观锁

3. dirty:通过检查发生变动过的属性实现乐观锁

4. all:通过检查所有属性实现乐观锁

例子:
1)Hibernate悲观锁:

1>POJO类

    
    
  1. public class PersimisticLocking {  
  2.  private int id;  
  3.    
  4.  private String Item;  
  5.    
  6.  private int price;  
  7. //省略setter、getter方法  

2>、POJO类的映射文件

    
    
  1.   <? xml   version = "1.0" ?>  
  2.  <!DOCTYPE hibernate-mapping PUBLIC   
  3.      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  4.      "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >  
  5.   < hibernate-mapping   package = "org.apple.hibernate" >  
  6.       < class   name = "PersimisticLocking"   table = "t_persimisticLocking" >  
  7.           < id   name = "id" >  
  8.               < generator   class = "native" />  
  9.           </ id >  
  10.          < property   name = "item" />  
  11.          < property   name = "price" />  
  12.      </ class >  
  13. </ hibernate-mapping >  

3>、加载测试方法

    
    
  1. public void testLoad1()  
  2.      {  
  3.          Session  session  =  null ;  
  4.          try {  
  5.               session  =  HibernateUtil .getSession();  
  6.              session.beginTransaction();  
  7.              OptimisticLocking  o  = (OptimisticLocking)session.load(OptimisticLocking.class, 1);  
  8.              System.out.println(" o.item ="+o.getItem());  
  9.              System.out.println(" o.price ="+o.getPrice());  
  10.             System.out.println(" o.version ="+o.getVersion());  
  11.             o.setPrice(o.getPrice()-10);  
  12.             session.update(o);  
  13.             session.beginTransaction().commit();  
  14.         } catch (Exception e) {  
  15.             // TODO: handle exception  
  16.             e.printStackTrace();  
  17.             session.beginTransaction().rollback();  
  18.         }finally{  
  19.             HibernateUtil.closeSession(session);  
  20.         }  
  21.           
  22.     } 

可以设置另外类似的方法,不枷锁,先对上面的测试代码设置断点,点debug一部分,再运行不枷锁的,可以看到,如果上面方法不释放锁的话,下面的数据就会造成无限期的等待。

2、Hibernate乐观锁:

1>在悲观锁的基础上加入private int version;和相关的setter、getter方法。

2>映射文件配置在class标签里面加入optimistic-lock="version",然后在的id标签后面加入<version name="version"/>

3>测试方法:

    
    
  1. public void testLoad1()  
  2.      {  
  3.          Session  session  =  null ;  
  4.          try {  
  5.               session  =  HibernateUtil .getSession();  
  6.              session.beginTransaction();  
  7.              OptimisticLocking  o  = (OptimisticLocking)session.load(OptimisticLocking.class, 1);  
  8.              System.out.println(" o.item ="+o.getItem());  
  9.              System.out.println(" o.price ="+o.getPrice());  
  10.             System.out.println(" o.version ="+o.getVersion());  
  11.             o.setPrice(o.getPrice()-10);  
  12.             session.update(o);  
  13.             session.beginTransaction().commit();  
  14.         } catch (Exception e) {  
  15.             // TODO: handle exception  
  16.             e.printStackTrace();  
  17.             session.beginTransaction().rollback();  
  18.         }finally{  
  19.             HibernateUtil.closeSession(session);  
  20.         }  
  21.           
  22.     } 

在初始数据的时候,version为0,在没更新一次version都会在原来的基础上加1,通过version的版本来实现Hibernate乐观锁。

在上面的测试方法里面复制成另外一个方法,对上面的方法进行设置断点,然后单步调试几部,到NO.11行的时候暂停,此时对复制的另外方法运行,然后再运行完上面的方法,就会抛出异常,所以,在实际的项目开发中,可以通过对异常进行出来,这样就会实现并发访问。

你可能感兴趣的:(Hibernate)