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_test`的项目,编写对应的实体类、映射文件以及测试用例,模拟并发场景,来深入理解并对比悲观锁和乐观锁的差异和效果。 总之,理解并合理运用悲观锁和乐观锁...
Hibernate 中有两种锁机制:悲观锁和乐观锁。 一、悲观锁(Pessimistic Locking) 悲观锁是一种预防并发访问的机制,Hibernate 通过对数据库的锁定来实现。悲观锁假定任何时刻存取数据时,都可能有另一个客户也...
主要分为两种类型:乐观锁(Optimistic Locking)和悲观锁(Pessimistic Locking)。 **悲观锁(Pessimistic Locking)** 悲观锁假设数据在任何时候都可能发生并发冲突,因此在数据读取时就对其进行锁定,确保在...
**Hibernate**作为一种流行的Java持久层框架,提供了多种机制来处理并发控制问题,其中最常用的就是**乐观锁**和**悲观锁**。本文将详细介绍这两种锁的原理、应用场景以及如何在Hibernate中实现。 #### 二、悲观锁...
本文主要讨论的是Hibernate框架中两种锁机制的使用:乐观锁和悲观锁。 首先,让我们深入理解悲观锁(Pessimistic Locking)。悲观锁正如其名字所示,假设并发环境中数据会被频繁修改,所以在整个数据处理过程中,它...
### Hibernate的乐观锁和悲观锁 #### 一、引言 在软件开发中,尤其是在涉及大量并发操作的应用场景下,确保数据的一致性和完整性是非常重要的。对于基于Java Web的应用而言,Hibernate作为一款流行的ORM框架,提供...
Hibernate中乐观锁的应用** 在Hibernate中,可以通过实体类中的版本字段来实现乐观锁。例如: ```java @Entity public class TUser { private int id; @Version private int version; // 版本号字段 // ...
**悲观锁**(Pessimistic Lock)与**乐观锁**(Optimistic Lock)是数据库和对象关系映射(ORM)框架中两种重要的锁定机制,主要用于解决并发控制问题。 ##### 悲观锁 悲观锁假设数据会被频繁地并发访问和修改,...
本教程主要聚焦于Hibernate中的事务并发处理,包括悲观锁和乐观锁两种策略,这对于我们理解如何在高并发环境中确保数据的一致性和完整性至关重要。 首先,事务是数据库操作的基本单元,它确保一组操作要么全部成功...
为了解决这些问题,通常会采用两种锁机制——乐观锁和悲观锁。 1. 乐观锁(Optimistic Locking)乐观锁假设并发冲突较少,因此在数据读取时不加锁,而在更新时检查数据是否已被其他事务修改。例如,Hibernate通过...
Hibernate 支持两种类型的锁来处理并发问题:悲观锁(pessimistic lock)和乐观锁(optimistic lock)。 #### 9. Struts2 的拦截器 Struts2 中可以使用 `<s.token>` 标签来解决重复提交问题,并使用 `<s.text>` ...
- **LockMode**:控制对实体加锁的方式,例如`Optimistic`或`Pessimistic`。 - **Criterion组合**:可以通过`Junction`类组合多个`Criterion`对象,实现更复杂的查询条件。 #### 实战应用 1. **使用Restrictions...