hibernate学习之三(悲观锁与乐观锁)

悲观锁与乐观锁

悲观锁

悲观锁(pessimistic lock)是指在每次操作数据时,总是悲观地认为会有其他事务操作同一数据,因此,在整个数据处理过程中,会把数据处于锁定状态。

悲观锁具有排他性,一般由数据库实现。在锁定时间内,其他事务不能对数据进行存取等操作,这可能导致长时间的等待问题。

通常在应用中会设定如下两种锁模式。

1)LockMode.UPGRADE

该模式不管缓存中是否存在对象,总是通过 select 语句到数据库中加载该对象,如果映射文件中设置了版本元素,则执行版本检查,比较缓存中的对象是否与数据库中对象的版本一致,如果数据库系统支持悲观锁(如 MySQL),则执行 elect…for update 语句,如果不支持(如 Sybase),则执行普通 select 语句。

2)LockMode.UPGRADE_NOWAIT

该模式与 LockMode.UPGRADE 具有同样的功能,是 Oracle 数据库特有的锁模式,会执行 select…for update nowait 语句。

nowait 表示如果执行 select 语句的事务不成立则获得悲观锁,它不会等待其他事务释放锁,而是立刻抛出锁定异常。

下面通过丢失更新的案例演示悲观锁的使用。

案例主要代码:

@Getter
@Setter
public class Inventory {

private int itemNo;

private String itemName;

private int quantity;

}
<hibernate-mapping>
   <class name="com.bjsxt.hibernate.Inventory" table="t_inventory">
      <id name="itemNo">
         <generator class="native"/>
      </id>
      <property name="itemName"/>
      <property name="quantity"/>
   </class>
</hibernate-mapping>

使用:

Inventory inv = (Inventory)session.load(Inventory.class, 1, LockMode.UPGRADE);

悲观锁不支持懒加载,也就是说一加锁懒加载就失效了

乐观锁

相对于悲观锁而言,乐观锁(optimistic lock)通常认为多个事务同时操作同一数据的情况很少发生,因此乐观锁不进行数据库层次上的锁定,而是基于数据版本(Version)标识实现应用程序级别上的锁定机制,这既能保证多个事务的并发操作,又能有效防止第二类丢失更新的发生。

数据版本标识是通过为数据表增加一个 version 字段实现的。增加 version 字段后,程序在读取数据时,会将版本号一同读出,之后在更新此数据时,会将此版本号加一。

在提交数据时,将现有的版本号与数据表对应记录的版本号进行对比,如果提交数据的版本号大于数据表中的版本号,则允许更新数据,否则禁止更新数据。

​ 主要代码:

 @Setter
 @Getter
 public class Inventory {

   private int itemNo;
   
   private String itemName;
   
   private int quantity;
   
   private int version1;
   
}
<hibernate-mapping>
   <class name="com.bjsxt.hibernate.Inventory" table="t_inventory" optimistic-lock="version">
      <id name="itemNo">
         <generator class="native"/>
      </id>
      <version name="version1"/>
      <property name="itemName"/>
      <property name="quantity"/>
   </class>
</hibernate-mapping>

Hibernate 的乐观锁是以 id 和 version 决定更新对象的。

tive"/>




注意:**hibernate默认懒加载是开启的。**

针对于开启懒加载后,对数据库进行查询,会出现一下的情况:

```java
//不会发出sql
Group group = (Group)session.load(Group.class, 1);

//不会发出sql
System.out.println("group.id=" + group.getId());

//会发出sql
System.out.println("group.name=" + group.getName());

并且:hibernate支持lazy策略只有在session打开状态下有效,当session关闭后,不能正确输出,抛出LazyInitializationException 异常,因为session已经关闭。

悲观锁与乐观锁

悲观锁

悲观锁(pessimistic lock)是指在每次操作数据时,总是悲观地认为会有其他事务操作同一数据,因此,在整个数据处理过程中,会把数据处于锁定状态。

悲观锁具有排他性,一般由数据库实现。在锁定时间内,其他事务不能对数据进行存取等操作,这可能导致长时间的等待问题。

通常在应用中会设定如下两种锁模式。

1)LockMode.UPGRADE

该模式不管缓存中是否存在对象,总是通过 select 语句到数据库中加载该对象,如果映射文件中设置了版本元素,则执行版本检查,比较缓存中的对象是否与数据库中对象的版本一致,如果数据库系统支持悲观锁(如 MySQL),则执行 elect…for update 语句,如果不支持(如 Sybase),则执行普通 select 语句。

2)LockMode.UPGRADE_NOWAIT

该模式与 LockMode.UPGRADE 具有同样的功能,是 Oracle 数据库特有的锁模式,会执行 select…for update nowait 语句。

nowait 表示如果执行 select 语句的事务不成立则获得悲观锁,它不会等待其他事务释放锁,而是立刻抛出锁定异常。

下面通过丢失更新的案例演示悲观锁的使用。

案例主要代码:

@Getter
@Setter
public class Inventory {

private int itemNo;

private String itemName;

private int quantity;

}
<hibernate-mapping>
   <class name="com.bjsxt.hibernate.Inventory" table="t_inventory">
      <id name="itemNo">
         <generator class="native"/>
      </id>
      <property name="itemName"/>
      <property name="quantity"/>
   </class>
</hibernate-mapping>

使用:

Inventory inv = (Inventory)session.load(Inventory.class, 1, LockMode.UPGRADE);

悲观锁不支持懒加载,也就是说一加锁懒加载就失效了

乐观锁

相对于悲观锁而言,乐观锁(optimistic lock)通常认为多个事务同时操作同一数据的情况很少发生,因此乐观锁不进行数据库层次上的锁定,而是基于数据版本(Version)标识实现应用程序级别上的锁定机制,这既能保证多个事务的并发操作,又能有效防止第二类丢失更新的发生。

数据版本标识是通过为数据表增加一个 version 字段实现的。增加 version 字段后,程序在读取数据时,会将版本号一同读出,之后在更新此数据时,会将此版本号加一。

在提交数据时,将现有的版本号与数据表对应记录的版本号进行对比,如果提交数据的版本号大于数据表中的版本号,则允许更新数据,否则禁止更新数据。

​ 主要代码:

 @Setter
 @Getter
 public class Inventory {

   private int itemNo;
   
   private String itemName;
   
   private int quantity;
   
   private int version1;
   
}
<hibernate-mapping>
   <class name="com.bjsxt.hibernate.Inventory" table="t_inventory" optimistic-lock="version">
      <id name="itemNo">
         <generator class="native"/>
      </id>
      <version name="version1"/>
      <property name="itemName"/>
      <property name="quantity"/>
   </class>
</hibernate-mapping>

Hibernate 的乐观锁是以 id 和 version 决定更新对象的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值