即通常所说的“悲观锁(Pessimistic Locking)”和“乐观锁(OptimisticLocking)”。
悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
Hibernate的加锁模式有:
Ø LockMode.NONE : 无锁机制。
Ø LockMode.WRITE:Hibernate在Insert和Update记录的时候会自动
获取。
Ø LockMode.READ :Hibernate在读取记录的时候会自动获取。
以上这三种锁机制一般由Hibernate内部使用,如Hibernate为了保证Update
过程中对象不会被外界修改,会在save方法实现中自动为目标对象加上WRITE锁。
Ø LockMode.UPGRADE :利用数据库的forupdate子句加锁。
Ø LockMode. UPGRADE_NOWAIT :Oracle的特定实现,利用Oracle的for updatenowait子句实现加锁。
2
Query 3
query.setLockMode( 4
获取数据
上面这两种锁机制是我们在应用层较为常用的,加锁一般通过以下方法实现:
Criteria.setLockMode
Query.setLockMode
Session.lock
注意,只有在查询开始之前(也就是Hiberate 生成SQL 之前)设定加锁,才会真正通过数据库的锁机制进行加锁处理,否则,数据已经通过不包含for update 子句的SelectSQL加载进来,所谓数据库加锁也就无从谈起。
乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个“version”字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
1. 首先为TUser的class描述符添加optimistic-lock属性:
name
table
dynamic
dynamic
optimistic
……
代码内容
name
table
dynamic
dynamic
optimistic
10
name 11
column 12
type 13
14
15
16
17
18
column 19
name 20
type 21
22
…… 23
24
25

注意version 节点必须出现在ID 节点之后。
代码内容
2
criteria.add(Expression.eq( 3
List 4
TUser 5
Transaction 6
user.setUserType( 7
8

每次对TUser进行更新的时候,我们可以发现,数据库中的version都在递增。 而如果我们尝试在tx.commit之前,启动另外一个Session,对名为Erica 的用户进行操作,以模拟并发更新时的情形:
代码内容
Criteria
criteria.add(Expression.eq(
Session
Criteria
criteria2.add(Expression.eq(
List
List
TUser 10
Transaction 11
Transaction 12
user2.setUserType( 13
tx2.commit(); 14
user.setUserType( 15
tx.commit(); 16

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

被折叠的 条评论
为什么被折叠?



