Hibernate乐观锁和悲观锁

来源:互联网 发布:4g网络制式有哪些 编辑:程序博客网 时间:2024/05/18 09:06

Hibernate支持两种锁机制: 即通常所说的“悲观锁(Pessimistic Locking)”和 “乐观锁(OptimisticLocking)”。

Hibernate的悲观锁加锁模式有:
   1、LockMode.NONE : 无锁机制。
   2、LockMode.WRITE :Hibernate在Insert和Update记录的时候会自动获取。
   3、LockMode.READ : Hibernate在读取记录的时候会自动获取。
以上这三种锁机制一般由Hibernate内部使用,如Hibernate为了保证Update
过程中对象不会被外界修改,会在save方法实现中自动为目标对象加上WRITE锁。
Ø LockMode.UPGRADE :利用数据库的for update子句加锁。
Ø LockMode. UPGRADE_NOWAIT :Oracle的特定实现,利用Oracle的for update nowait子句实现加锁。


eg:

Emp e=(Emp)session.get(Emp.class, 10,LockMode.UPGRADE);
语句:Hibernate: 
    select
        emp0_.EMPNO as EMPNO0_0_,
        emp0_.version as version0_0_,
        emp0_.DEPTNO as DEPTNO0_0_,
        emp0_.ENAME as ENAME0_0_,
        emp0_.JOB as JOB0_0_,
        emp0_.MGR as MGR0_0_,
        emp0_.HIREDATE as HIREDATE0_0_,
        emp0_.SAL as SAL0_0_,
        emp0_.COMM as COMM0_0_ 
    from
        scott.emp emp0_ 
    where
        emp0_.EMPNO=? for update


加锁一般通过以下方法实现:

Criteria.setLockMode 
Query.setLockMode 
Session.lock 
注意,只有在查询开始之前(也就是Hiberate 生成SQL 之前)设定加锁,才会 真正通过数据库的锁机制进行加锁处理,否则,数据已经通
过不包含for update 子句的Select SQL加载进来,所谓数据库加锁也就无从谈起。 

XML配置:

<hibernate-mapping>    <class name="org.han.entity.Dept" table="dept" schema="scott" optimistic-lock="version">        <id name="deptno" type="java.lang.Integer">            <column name="DEPTNO" precision="2" scale="0" />            <generator class="assigned" />        </id>        <version name="version" type="java.lang.Integer"></version>        <property name="dname" type="java.lang.String">            <column name="DNAME" length="14" />        </property>        <property name="loc" type="java.lang.String" lazy="false">            <column name="LOC" length="13" />        </property>        <set name="emps" inverse="true" fetch="select" lazy="true">            <key>                <column name="DEPTNO" precision="2" scale="0" />            </key>            <one-to-many class="org.han.entity.Emp" />        </set>    </class></hibernate-mapping>



实体类增加属性version:

private Integer deptno;private String dname;private String loc;private Integer version;private Set emps = new HashSet();

之后只要对数据库进行有意义的操作就会对version更新+1(version字段不能为空),事务提交前比较版本号是否一致


悲观锁与乐观锁的比较:
        悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受;
相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。乐观锁机制往往基于系统中的数据存储逻辑,因此也具备一定的局限性,如在上例中,由于乐观锁机制是在我们的系统中实现,来自外部系统的更新操作不受我们系统的控制,因此可能会造成脏数据被更新到数据库中。在
系统设计阶段,我们应该充分考虑到这些情况出现的可能性,并进行相应调整(如将乐观锁策略在数据库存储过程中实现,对外只开放基于此存储过程的数据更新途径,而不是将数据库表直接对外公开)。
Hibernate 在其数据访问引擎中内置了乐观锁实现。如果不用考虑外部系统对数据库的更新操作,利用Hibernate提供的透明化乐观锁实现,将大大提升我们的生产力。
Hibernate中可以通过class描述符的optimistic-lock属性结合version描述符指定。
optimistic-lock属性有如下可选取值:
Ø none
无乐观锁
Ø version
通过版本机制实现乐观锁
Ø dirty
通过检查发生变动过的属性实现乐观锁
Ø all
通过检查所有属性实现乐观锁
其中通过version实现的乐观锁机制是Hibernate官方推荐的乐观锁实现,同时也是Hibernate中,目前唯一在数据对象脱离Session发生修改的情况下依然有效的锁机制。因此,一般情况下,我们都选择version方式作为Hibernate乐观锁实现机制。  

原创粉丝点击