Hibernate 悲观锁与乐观锁

来源:互联网 发布:宏观数据 编辑:程序博客网 时间:2024/05/01 12:18

一、悲观锁

       悲观锁具有强排他性,依靠数据库的锁机制来实现的。当在某一行数据加上悲观锁后,在这一行数据的整个处理过程中,只有一个用户可以访问它,其他用户被排除在外。只有等到当前用户释放锁后,其他用户才能访问这一数据。悲观锁在并发性能上差强人意。它的加锁时间可能会很长,所以一般用在小型快速处理的事务上。

     在Hibernate中,可以用如下三种方式对数据进行加锁   

           1、Session.load(),指定特定 LockMode
           2、Session.lock().
           3、 Query.setLockMode()

      LockMode定义如下不同的锁级别:

           1、 LockMode.WRITE     当Hibernate更新或插入一行的时候自动获取

           2、LockMode.UPGRADE(常用)  在支持for update子句的数据库上,使用 SELECT ... FOR UPDATE进行加锁.  
           3、LockMode.UPGRADE_NOWAIT(常用) 用于 Oracle数据库中,作用效果和UPGRADE一样
           4、LockMode.UPGRADE_SKIPLOCKED  在对数据行进行加锁操作时,如果发现数据行被锁定,就跳过处理。这样for update就只针对未加锁的数据行进行处理加锁。在Oracle中的用法 —SELECT ... FOR UPDATE SKIP LOCKED ,在SQL Server中的用法— SELECT ... with (rowlock,updlock,readpast)
           5、LockMode.READ   当在可重复读或序列化隔离级别上,Hibernate在加载数据时就会自动加上这个级别的锁
           6、LockMode.NONE  无锁。所有对象在事务结束时都处在这个锁级别上,通过调用session.update()或session.saveOrUpdate(),游离态和临时态对象就可以进入无锁

          举例:

            String hqlStr ="from tb_student  stu where stu.age=17";
              Query query = session.createQuery(hqlStr);
              query.setLockMode("student",LockMode.UPGRADE); // 加锁
              List students = query.list();// 执行查询,获取数据

二 、乐观锁

      乐观锁相比悲观锁在并发性能上有所提升,不独占资源。它基于数据版本记录机制实现的,在数据库表中增加一个version字段,在读数据时连同version字段一并读出,并对version进行加一操作,在提交数据时,将version的值与表中对应记录的Version字段值相比较,若大于,则更新操作,若小于,则冲突,视为过期数据。乐观锁适合长事务。另外,Hibernate会将任何version为null的对象视为游离态。

       乐观锁有两种实现方式

       1、专用的版本号—version

      2、timestamp

      第一种方式—@version

           @Entity
            public class Flight implements Serializable {
             ...
            @Version
            @Column(name="OPTLOCK")
            public Integer getVersion() { ... }   //可以是任意类型,只要定义并实现UserVersionType
        }

      第二种方式—timestamp

      如果你要控制的版本类型是Date orCalendar. 如:

    @Entity
    public class Flight implements Serializable {
      ...
     @Version
       public Date getLastUpdate() { ... }
     }

注:可以使用在对应属性上添加@org.hibernate.annotations.Generated(GenerationTime.ALWAYS)让version版本号有数据库生成。.

0 0
原创粉丝点击