在使用Hibernate的过程中,我们会遇到多人对同一个数据同时进行修改,这个时候就会产生脏数据,造成数据的不一致性。为了避免更新数据的丢失,Hibernate采用了锁的机制。
Hibernate提供了两种锁的机制:悲观锁和乐观锁
悲观锁:在数据有加载的时候就给其进行加锁,直到该锁被释放掉,其他用户才可以进行修改;
乐观锁:在对数据进行修改的时候,对数据采用版本号或者时间戳等方式来比较,数据是否一致性来实现加锁;
一、悲观锁
悲观锁是依靠数据库提供的锁机制。Hibernate是通过使用数据库的for update子句实现了悲观锁机制。
Hibernate有如下五种加锁机制
1、 LockMode.NONE:无锁机制;
2、 LockMode.WRITE:Hibernate在Insert和Update记录的时候会自动获取
3、 LockMode.READ:Hibernate在读取记录的时候会自动获取
4、 LockMode.UPGRADE:利用数据库的for update子句加锁
5、 LockMode.UPGRADE_NOWAIT:Oracle的特定实现,利用Oracle的for update nowait子句实现加锁
悲观加锁一般通过以下三种方法实现:
1、Criteria.setLockMode
2、Query.setLockMode
3、Session.lock
public void query(int id){ Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); String hql = "from Users as u where id= :id"; List list = session.createQuery(hql) .setLockMode("u", LockMode.UPGRADE) //执行加锁 .setInteger("id", id) .list(); for(Iterator iterator = list.iterator();iterator.hasNext();){ Users users = (Users) iterator.next(); System.out.println(users.getBirthday()); } }
select users0_.id as id0_, users0_.ver as ver0_, users0_.birthday as birthday0_, users0_.first_name as first4_0_, users0_.last_name as last5_0_ from Users users0_ with (updlock, rowlock) where users0_.id=?
悲观锁在对数据进行加锁后,会一直“霸占”该数据,直到释放掉,其他用户才可以对该数据进行更新。这里就存在一个问题,如果它一直占着不放,那么其他用户永远也不可能对该数据进行更新,这样就很不利于并发了。对于这个问题的解决方案,可以利用乐观锁。
二、乐观锁
乐观锁大多是基于数据版本记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个“version”字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
我们可以通过class描述符的optimistic-lock属性结合version描述符指定乐观锁。
1. none:无乐观锁
2. version:通过版本机制实现乐观锁
3. dirty:通过检查发生变动过的属性实现乐观锁
4. all:通过检查所有属性实现乐观锁
在实现乐观锁的持久化类我们需要为该持久化类增加一个version属性,并且提供相应的getter和setter方法。如下
public class Users { private int id; private Date birthday; private Name name; private int version; //舍掉getter和setter方法 }
<hibernate-mapping package="com.hibernate.domain"> <class name="Users" optimistic-lock="version"> <id name="id"> <generator class="native" /> </id> <version name="version" /> <property name="birthday" /> <!-- 映射组件元素 --> <component name="name"> <!-- 映射组件的name属性指向包含实体 --> <property name="firstName" column="first_name"/> <property name="lastName" column="last_name"/> </component> </class> </hibernate-mapping>
注意:version 节点必须出现在ID 节点之后。
在这里我们声明了一个version属性,该属性用于存放用户的版本信息。我们对user表每一次更新操作,都会引起version属性的变化:加1。如果我们尝试在tx.commit 之前,启动另外一个Session,对名为同一个用户进行操作,就是并发更新的情形了:
public void update(){ //开启事务tx1 Session session1 = HibernateUtil.getSession(); Transaction tx1 = session1.beginTransaction(); Users users1 = (Users) session1.get(Users.class, 1); //获取id为1的用户 //开启事务tx2 Session session2 = HibernateUtil.getSession(); Transaction tx2 = session2.beginTransaction(); Users users2 = (Users) session2.get(Users.class, 1); //获取id为1的用户 users1.getName().setFirstName("first name1"); users2.getName().setFirstName("first name2"); tx1.commit(); //..........1 tx2.commit(); //..........2 session1.close(); session2.clear(); }
执行以上代码,代码将在.....2处抛出StaleObjectStateException异常,并指出版本检查失败。
在这里是先提交者成功,后提交者失败。当前事务正在试图提交一个过期数据。通过捕捉这个异常,我们就可以在乐观锁校验失败时进行相应处理。
相关推荐
21.5 利用Hibernate的版本控制来实现乐观锁 21.5.1 使用元素 21.5.2 使用元素 21.5.3 对游离对象进行版本检查 21.5.4 强制更新版本 21.6 实现乐观锁的其他方法 21.7 小结 21.8 思考题 第22章 管理...
21.5 利用Hibernate的版本控制来实现乐观锁 21.5.1 使用元素 21.5.2 使用元素 21.5.3 对游离对象进行版本检查 21.5.4 强制更新版本 21.6 实现乐观锁的其他方法 21.7 小结 21.8 思考题 第22章 管理...
21.5 利用Hibernate的版本控制来实现乐观锁 21.5.1 使用元素 21.5.2 使用元素 21.5.3 对游离对象进行版本检查 21.5.4 强制更新版本 21.6 实现乐观锁的其他方法 21.7 小结 21.8 思考题 第22章 管理...
21.5 利用Hibernate的版本控制来实现乐观锁 21.5.1 使用元素 21.5.2 使用元素 21.5.3 对游离对象进行版本检查 21.5.4 强制更新版本 21.6 实现乐观锁的其他方法 21.7 小结 21.8 思考题 第22章 管理...
少儿编程scratch项目源代码文件案例素材-纸人伙计.zip
scratch少儿编程逻辑思维游戏源码-忍者罗伊 V5.zip
scratch少儿编程逻辑思维游戏源码-跑和枪.zip
前端开发_基于jQuery和EasyUI框架_企业级Web应用UI组件库与后台管理系统模板_提供GPL开源版本和商业授权版本的双重授权模式_适用于快速构建响应式管理后台和复杂数据可
少儿编程scratch项目源代码文件案例素材-纸格通关 云变量.zip
微信机器人开发_Wechaty框架_百度云主机部署_自然语言处理_消息自动化处理_多媒体文件管理_聊天记录持久化_表情包导出_语音视频自动保存_文件管理系统集成_跨平台数据同步_个
少儿编程scratch项目源代码文件案例素材-钻机机器人.zip
少儿编程scratch项目源代码文件案例素材-作战基地.zip
云计算_微服务分布式架构SpringCloudSpringBootDubboVuejs_互联网云快速开发框架敏捷开发系统代码生成工作流CMS图表统计地图统计_免费开源JAVA企业
scratch少儿编程逻辑思维游戏源码-日落塔.zip
Tobapuww_GPT-Recovery-Files_12888_1745866661386
少儿编程scratch项目源代码文件案例素材-战斗竞技场.zip
scratch少儿编程逻辑思维游戏源码-球球大作战.zip
聚合支付系统/官方个人免签系统/三方支付系统稳定安全高并发 附教程 系统采用FastAdmin框架独立全新开发,安全稳定,系统支持代理、商户、码商等业务逻辑。 针对最近一些JD,TB等业务定制,子账号业务逻辑API 非常详细,方便内置对接! IP白名单 业务逻辑 支持IP白名单,黑名单,全局白名单,全局黑名单,保障系统的安全。 接口验签名 采用支付宝RSA加密接口方式,防止篡改数据,导致对账困难,资金大量损失,无故少钱 对接灵活 全部对接参数灵活操作 风控完善 轮询、交易金额、随机金额、最大金额、最小金额等 测试环境: Nginx+PHP7.0+MySQL5.6 网站运行目录:/public 伪静态设置为:thinkphp规则 数据库信息修改路径:/application/database.php
校园社交服务_微信小程序云开发_公告资讯失物招领二手交易兼职招聘表白墙_为高校师生提供一站式校园生活服务平台包含校园动态通知课程表查询失物发布与认领二手物品交易平台兼职信息发布与求
yinghuayu2377_myFTPDemo_32152_1745866651913