Hibernate实现悲观锁和乐观锁代码介绍

 更新时间:2017年09月27日 16:30:54   作者:光仔December  
这篇文章主要介绍了Hibernate实现悲观锁和乐观锁的有关内容,涉及hibernate的隔离机制,以及实现悲观锁和乐观锁的代码实现,需要的朋友可以了解下。

四种隔离机制不要忘记:(1,2,4,8)

1.read-uncommitted:能够去读那些没有提交的数据(允许脏读的存在)

2.read-committed:不会出现脏读,因为只有另一个事务提交才会读取来结果,但仍然会出现不可重复读和幻读现象。

4.repeatable read: MySQL 默认。可重复读,读数据读出来之后给它加把锁,其他人先别更新,等我用完了你再更新。你的事务没完,其他事务就不可能改这条记录。

8.serializable:序列化,最高级别。一个一个来,不去并发。效率最低。

hibernate的隔离机制

i.hibernate.connection.isolation=2

ii.用悲观锁解决:repeatable read的问题(依赖于数据库的锁)

a)LockMode.None 无锁的机制,Transaction结束时,切换到此模式

b)LockMode.read 在查询的时候 hibernate会自动获取锁

c)LockMode.write insert update hibernate会自动获取锁

d)以上3中锁的模式,是hibernate内部使用的

e)LockMode.UPGRADE_NOWAIT ORACLE支持的锁的方式

例子:

Account.java:

package com.bjsxt.hibernate; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
@Entity 
public class Account { 
private int id; 
private int balance; //BigDecimal 
@Id 
@GeneratedValue 
public int getId() { 
return id; 
} 
public void setId(int id) { 
this.id = id; 
} 
public int getBalance() { 
return balance; 
} 
public void setBalance(int balance) { 
this.balance = balance; 
} 
} 

hibernate.cfg.xml中配置:

<mapping class="com.bjsxt.hibernate.Account"/> 

测试:

@Test 
public void testSave() { 
Session session = sf.openSession(); 
session.beginTransaction(); 
Account a = new Account(); 
a.setBalance(100); 
session.save(a); 
session.getTransaction().commit(); 
session.close(); 
} 
@Test 
public void testOperation1() { 
Session session = sf.openSession(); 
session.beginTransaction(); 
Account a = (Account)session.load(Account.class, 1); 
int balance = a.getBalance(); 
//do some caculations 
balance = balance - 10; 
//在保存时很有可能会把在同一时期修改的给覆盖掉 
//这个时候上一把"锁"就可以避免这个问题 
a.setBalance(balance); 
session.getTransaction().commit(); 
session.close(); 
} 
//下面这个就是对上面那个例子做的修改 
@Test 
public void testPessimisticLock() { 
Session session = sf.openSession(); 
session.beginTransaction(); 
//给它加把锁,加锁的机制上面已经提到了 
Account a = (Account)session.load(Account.class, 1, LockMode.UPGRADE); 
int balance = a.getBalance(); 
//do some caculation 
balance = balance - 10; 
a.setBalance(balance); 
session.getTransaction().commit(); 
session.close(); 
} 

这是依赖于数据库的锁的,也就是给数据库一个指令,要求数据库帮忙加锁。
——————————————————————————————————————

iii.Hibernate(JPA)乐观锁定(ReadCommitted)

这不是依赖数据库加锁的,是在程序中加锁的。

举个例子:一个数据需要隔离机制(不能重复读),这个时候在更新的字段上加"版本号"(version字段),一旦有人给它update一下,这个值就加1(version+1)。

那么这种机制是如何产生隔离能力的呢?

原因是事务A读取字段的同时,事务B紧接着也读取这个字段,而且改了它,此时version变成1了。这个时候事务A就会检查字段是否被改变了,如果被改变它也做相应的改变,没有改变就不改。

乐观锁的实现:(@Version)

Account.java:

package com.bjsxt.hibernate;  
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.Version;  
@Entity 
public class Account { 
private int id; 
private int balance; 
private int version;  
@Version//加了这个注解就说明这个是专门用来做版本标注的 
public int getVersion() { 
return version; 
} 
public void setVersion(int version) { 
this.version = version; 
} 
@Id 
@GeneratedValue 
public int getId() { 
return id; 
} 
public void setId(int id) { 
this.id = id; 
} 
public int getBalance() { 
return balance; 
} 
public void setBalance(int balance) { 
this.balance = balance; 
} 
} 

测试:

 @Test 
public void testSave() { 
Session session = sf.openSession(); 
session.beginTransaction(); 
Account a = new Account(); 
a.setBalance(100); 
session.save(a); 
session.getTransaction().commit(); 
session.close(); 
} 
@Test 
public void testOptimisticLock() { 
Session session = sf.openSession(); 
Session session2 = sf.openSession(); 
session.beginTransaction(); 
Account a1 = (Account) session.load(Account.class, 1); 
session2.beginTransaction(); 
Account a2 = (Account) session2.load(Account.class, 1); 
a1.setBalance(900); 
a2.setBalance(1100); 
//第一个session一旦提交,version就会+1 
session.getTransaction().commit(); 
System.out.println(a1.getVersion()); 
//第二个session提交的时候,一看version不一样就会报错 
//出了错误做个记录,下次再提交(也可以用其他方法) 
        session2.getTransaction().commit(); 
System.out.println(a2.getVersion()); 
session.close(); 
session2.close(); 
} 

悲观乐观的区别:悲观锁认为一定会受到影响,我加锁谁也别想动。
乐观锁,没出事就好,出了事我再想办法解决。

总结

以上就是本文关于Hibernate实现悲观锁和乐观锁代码介绍的全部内容,希望对大家学习hibernate有所帮助。有什么问题可以随时留言,小编会及时回复大家。感谢大家对本站的支持。

相关文章

  • Java redis存Map对象类型数据的实现

    Java redis存Map对象类型数据的实现

    本文主要介绍了Java redis存Map<String,RedisCustom>对象类型数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • SpringBoot集成Lettuce客户端操作Redis的实现

    SpringBoot集成Lettuce客户端操作Redis的实现

    本文主要介绍了SpringBoot集成Lettuce客户端操作Redis的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-11-11
  • springboot运行jar生成的日志到指定文件进行管理方式

    springboot运行jar生成的日志到指定文件进行管理方式

    这篇文章主要介绍了springboot运行jar生成的日志到指定文件进行管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Java中isAssignableFrom的用法详解

    Java中isAssignableFrom的用法详解

    下面小编就为大家带来一篇Java中isAssignableFrom的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • 基于HttpServletRequest 相关常用方法的应用

    基于HttpServletRequest 相关常用方法的应用

    本篇文章小编为大家介绍,基于HttpServletRequest 相关常用方法的应用,需要的朋友参考下
    2013-04-04
  • mybatis双重foreach如何实现遍历map中的两个list数组

    mybatis双重foreach如何实现遍历map中的两个list数组

    本文介绍了如何解析前端传递的JSON字符串并在Java后台动态构建SQL查询条件,首先,通过JSONArray.fromObject()将JSON字符串转化为JSONArray对象,遍历JSONArray,从中提取name和infos,构建成Map对象用于Mybatis SQL映射
    2024-09-09
  • 一文带你学会规则引擎Drools的应用

    一文带你学会规则引擎Drools的应用

    Drools 就是一个开源的业务规则引擎,可以很容易地与 spring boot 应用程序集成,这篇文章就来和大家详细聊聊Drools的具体应用,需要的可以参考一下
    2023-03-03
  • Java实现中序表达式的实例代码

    Java实现中序表达式的实例代码

    这篇文章主要介绍了Java实现中序表达式的实例代码,需要的朋友可以参考下
    2018-08-08
  • Spring boot基于JPA访问MySQL数据库的实现

    Spring boot基于JPA访问MySQL数据库的实现

    本文主要介绍了Spring boot基于JPA访问MySQL数据库的实现,Spring boot结合Jpa 能够简化创建 JPA 数据访问层和跨存储的持久层功能,用户的持久层Dao接口只需要继承定义好的接口,感兴趣的可以了解一下
    2021-06-06
  • JavaWeb 中的 Filter组件详解

    JavaWeb 中的 Filter组件详解

    本文详细介绍了JavaWeb中的Filter组件,包括其基本概念、工作原理、核心接口和类、配置方式以及常见应用示例,Filter可以实现请求预处理、响应后处理、链式处理等功能,通过配置文件或注解进行设置,适用于字符编码、身份认证、日志记录等多种场景,感兴趣的朋友一起学习吧
    2025-11-11

最新评论