Hibernate
中的悲观锁(
pessimistic lock
)和乐观锁(
optimistic lock
)
悲观锁(
pessimistic lock
):
通常是由数据库机制实现的,在整个过程中把数据锁住(查询时),只要事务不释放(提交或回滚),任何用户都不能查看和修改。锁主要是解决并发性问题。
通过
jdbc
实现时
sql
语句只要在整个语句之后加
for update
即可。例如:
select …for update
Hibernate
中加载一个持久化类时需要用
load
方法
这个方法是对普通的
load
的重载。
如:
Student inv=
(
Student
)
session.load(Student
.class,”1001”,LOCKMODE.UPGRADE);
这时需要说明一个问题,这样就加了锁锁的类型可以根据
LOCKMODE
的值决定。加了锁之后,
Hibernate
的
lazy
策略就失效了,此时就发了
sql
语句,因为需要把这个对象加载进来锁住,所以发了
SQl
语句。当有一个方法通过悲观锁机制加载某个对象的时候,对这个对象进行了一系列的操作,在进行操作的时候,也就是只要事务未提交,这个锁就一直存在。当另外一个方法加载这个对象的时候(两个对象是一个对象,即唯一标示符的值是相同的)只会发出查询语句,停止不动,因为,前一个方法使用了悲观锁机制加载的这个对象,并没有结束事务(提交或回滚),因此这时是排他的。当第一个方法提交了事务,第二个方法才可以加载成功并按照自己的意愿执行其所有操作。
悲观锁的使用:悲观锁解决了更新丢失(
lost update
)问题,但是也带来了并发问题
à
并发不好。但是,如果在某个需求中,需要很多,很频繁的并发操作,特别是,某个操作或事务又会占用很多时间时,其他操作只能静而后之了。要看具体应用了。
Hibernate
的加锁模式有:
Ø LockMode.NONE
:
无锁机制。
Ø LockMode.WRITE
:
Hibernate
在
Insert
和
Update
记录的时候会自动
获取。
Ø LockMode.READ
:
Hibernate
在读取记录的时候会自动获取。
以上这三种锁机制一般由
Hibernate
内部使用,如
Hibernate
为了保证
Update
过程中对象不会被外界修改,会在
save
方法实现中自动为目标对象加上
WRITE
锁。
Ø LockMode.UPGRADE
:利用数据库的
for update
子句加锁。
Ø LockMode. UPGRADE_NOWAIT
:
Oracle
的特定实现,利用
Oracle
的
for
update nowait
子句实现加锁。
乐观锁(
optimistic
):
乐观锁其实不是一种锁,也就不是锁住的问题,而是给数据库表加入了一个字段(可以使版本号(
version
),也可以使一个时间戳(
timestamp
)),或是进行全部字段
/
脏数据字段比较(这种方式适合于以前遗留下来的系统,在不更改原来表结构的时候使用这种策略)来确定数据是否被修改过,一般的应用是采用数据版本的方式(
version
)实现,在读取数据的时候将
version
读取出来,在保存数据的时候判断
version
的值是否小于数据库中的
version
的值,小于则不允许更新,否则可以更新。
使用
version
实现乐观锁(推荐使用):在一个事务提交后就会更改数据库,数据库中
version
的值会自动加
1
。实现步骤
à
1
、在持久化类中加入
version
属性,生成其
getter
和
setter
方法。
2
、在配置文件中的
<class>
标签中配置一个属性
optimistic-lock=”version”
(这个属性的默认值就是
version
,可以不进行配置,但建议配置上)
3
、对
version
字段进行映射,使用
version
标签(这个字段的映射必须在
id
标签的后面第一位)
à
<version
name=”version”/>
细节分析
à
在一个事务加载某个持久化类时,对这个对象进行了一系列操作,但是还没有提交事务,于此同时,另外一个事物也加载了这个持久化类,并完成了一系列的操作后提交了事务,然后,第一个事务这时也要提交事务了,这样就会抛出一个异常
à
org.hibernate.StableObjectStateException:Rows was updated or deleted by another transaction…
,原因是这样的:当一个事务提交时会发出这样一条
SQL
语句
à
update
表名
set
所有表属性
=? where id(
唯一标示符值
)=? and version=?
这个语句中
version=?
是最关键的。以上说的那个例子中,第一个事务拿的是自己的旧的
version
值,进行更更新,而第二个事务在提交后,已经改变了
version
,变成了新的
version
值了,这样第一个事务提交事务时发出的
update
表名
set
所有表属性
=? where id(
唯一标示符值
) =? and version=?
这条语句将会失败!就会抛出以上异常信息。
乐观锁:适合于高并发。
optimistic-lock
属性有如下可选取值:
Ø none
无乐观锁
Ø version
通过版本机制实现乐观锁
Ø dirty
通过检查发生变动过的属性实现乐观锁
Ø all
通过检查所有属性实现乐观锁
分享到:
相关推荐
Hibernate锁机制_悲观锁和乐观锁
悲观锁(hibernate_pessimistic) 30 乐观锁(hibernate_optimistic) 32 HQL查询(hibernate_hql) 34 补充:SQL join连接 40 缓存 44 一级缓存 44 快取 45 hibernate二级缓存 47 Hibernate Gossip: 二级快取(Second...
RocksDB的Transaction分为两类:Pessimistic和Optimistic,类似悲观锁和乐观锁的区别,PessimisticTransaction的冲突检测和加锁是在事务中每次写操作之前做的(commit后释放),如果失败则该操作失败;...
11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...
11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...
11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...
11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...
在并发访问情况下,很有可能出现不可重复读等等读现象。为了更好的应对高并发,封锁...乐观锁和悲观锁不仅在关系数据库里应用,在Hibernate、Memcache等等也有相关概念。 悲观锁:也即悲观并发控制,Pessimistic Concur
11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...
这是Oracle数据库的一个工作示例,并附有博客文章“使用Spring Boot和JPA测试悲观锁处理” 此处有更多示例: 介绍 这个SpringBoot maven项目是我的一部分,您不仅可以找到对此的解释,还可以找到以下方面的理论背景...
11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 长生命周期session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...
乐观并发控制(Optimistic concurrency control) 10.4.1. 使用长生命周期带有自动版本化的会话 10.4.2. 使用带有自动版本化的多个会话 10.4.3. 应用程序自己进行版本检查 10.5. 会话断开连接(Session...
12.3. 乐观并发控制(Optimistic concurrency control) 12.3.1. 应用程序级别的版本检查(Application version checking) 12.3.2. 长生命周期session和自动版本化 12.3.3. 脱管对象(deatched object)和自动版本化 ...
12.3. 乐观并发控制(Optimistic concurrency control) 12.3.1. 应用程序级别的版本检查(Application version checking) 12.3.2. 长生命周期session和自动版本化 12.3.3. 脱管对象(deatched object)和自动版本化 ...
11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 长生命周期session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...
乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...
11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...
乐观并发控制(Optimistic concurrency control) 10.4.1. 使用长生命周期带有自动版本化的会话 10.4.2. 使用带有自动版本化的多个会话 10.4.3. 应用程序自己进行版本检查 10.5. 会话断开连接(Session...
乐观并发控制(Optimistic concurrency control) 12.3.1. 应用程序级别的版本检查(Application version checking) 12.3.2. 长生命周期session和自动版本化 12.3.3. 脱管对象(deatched object)和自动版本化 ...
11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...