Hibernate与悲观锁、乐观锁小总结
来源:互联网 发布:c语言的图形函数库 编辑:程序博客网 时间:2024/06/11 17:33
首先需要说明的是悲观锁和乐观锁不是hibernate提出的,而是JDBC里固有的两种事务加锁策略,这点在 javax.persistence.LockModeType 这个类有体现,hibernate实现和扩展了这两种策略。
4.0以上,有一个新特性,就是update语句的优化。
在我的hibernate中,如果修改了持久化对象的属性,hibernate会记录是哪个属性修改了,原理是通过setter,从而在update的时候只更新被修改的属性,而不是全部更新。
但是前提是必须是持久化对象。
悲观锁,网上介绍的很多,百度文库这个文章比较详细一点,以下总结几点
- 依赖数据库,需要其支持lock机制
- 需显示lock,会生成一条查询的sql,并且hibernate会将其放入PL(持久化池),放入PL后的对象属性修改(setter)会引起更新操作
- 对于4.0以上版本,持久化对象的属性修改会被hibernate记录,并在更新时仅仅更新修改过的属性,而不是更新所有属性
- 无法发现和处理第二类更新丢失,并且多线程并发有性能问题
- 因上面几点,4.0以后中这种类型的锁已经无多少用途,基本是保留API,保留hibernate可以使用悲观锁的机制
第一类更新丢失:事务A和事务B同时访问同一个数据,事务B先提交修改,事务A回滚操作。导致事务B的修改丢失
第二类更新丢失:事务A和事务B同时访问同一个数据,事务B先提交修改,事务A再提交。导致事务B的修改被覆盖
悲观锁不能发现第二类更新丢失问题,因为当A和B都获取同一行数据后,分别提交修改,因为是瞬时对象,即使merge,也可能出现覆盖的情况,因为merge会先查询数据库,假设这时A已经提交更新,那么就会读出A更新后的数据,然后merge方法会比较每个属性是否一致,不一致就会更新,从而导致更新丢失。
另外,使用merge方法时,如果当前session中已经存在一个id相同的持久化对象时,会抛出NonUniqueObjectException,可以使用session.clean 清除一级缓存。
个人认为,在多线程情况下使用悲观锁时应是如下形式:
Message message = (Message) session.get(Message.class , this.message.getUuid() , LockOptions.UPGRADE);this.message.setTitle(this.message.getTitle()+Math.random());BeanUtils.copyProperties(message, this.message);
利用4.0的特性,load或get一个对象,并加更新锁,然后修改属性,这里使用BeanUtils,当有属性调用setter,并且set一个不同的值时,就会触发该属性的更新操作。
乐观锁,通过程序机制来判断是否可以更新记录,推荐使用版本号验证机制,只是增加一个字段,但是性能较其他机制高很多,因仅需判断版本号就可以实现乐观锁机制了。
乐观锁定这个文章介绍很详细,大家可以去看看。
值得一说的是版本号字段的类型,推荐使用整数型integer,这也是官方推荐和默认的,而不建议使用timestamp,原因是有些数据库timestamp对应的类型精度不够,会产生版本无法匹配的问题和集群安全问题。
当使用乐观锁时,hibernate会生成类似下面的语句:
update hibernate.t_informations set version=?, title=?, content=? where uuid=? and version=?注意到where语句多出一条版本号的匹配,估计hibernate是这样判断的,当使用乐观锁时,如果这条语句更新了一条数据(有id条件,所以最多只能更新一条),就表示版本验证成功,反之不成功,抛出StaleObjectStateException,而且因为根本没有更新数据,所以不必回滚。
以上是版本号实现的乐观锁,估计其它方式也类似,本人没有测试,如果大家有什么不同意见,欢迎留言和讨论~
- Hibernate与悲观锁、乐观锁小总结
- Hibernate的乐观锁与悲观锁
- Hibernate的乐观锁与悲观锁
- Hibernate悲观锁与乐观锁
- Hibernate悲观锁与乐观锁
- Hibernate 乐观锁与悲观锁
- Hibernate 乐观锁与悲观锁
- hibernate中的悲观锁与乐观锁
- hibernate 乐观锁与悲观锁使用方法
- Hibernate读书笔记-----乐观锁与悲观锁
- hibernate 乐观锁与悲观锁使用
- hibernate 乐观锁与悲观锁使用
- Hibernate中的悲观锁与乐观锁
- hibernate 乐观锁与悲观锁使用
- hibernate 乐观锁与悲观锁使用
- hibernate 乐观锁与悲观锁使用
- hibernate 乐观锁与悲观锁使用
- hibernate 乐观锁与悲观锁
- php扩展开发(2)
- repo git
- Linux学习笔记---启动流程与主要启动记录区(MBR)
- hdu2084 数塔【简单DP】
- web.xml 中的listener、 filter、servlet 加载顺序及其详解
- Hibernate与悲观锁、乐观锁小总结
- sencha-touch下借助phoneGap实现拍照,二维码的功能
- C#邮件发送 批量发送邮件 发送邮件嵌入图片 添加附件
- RMAN原理(一)--内核数据包控制整个执行过程
- 字符设备驱动学习笔记----查询方式取得按键值
- PostgreSQL+phpPgAdmin总是登录失败(login failed)
- MotionEvent//动作事件
- 字符设备驱动学习笔记-----中断方式取得按键值
- HTTP 错误 500.23