Hibernate:不容易理解的 lock 和 merge
背景
lock 和 merge 在字面上很容易理解它们的语义,不过它们的实际行为所代表的语义范围要大一点,本文就简单的记录下来,还请朋友们多批评和指正。
Lock
官方的注释
1 /** 2 * Obtain the specified lock level upon the given object. This may be used to 3 * perform a version check (<tt>LockMode.READ</tt>), to upgrade to a pessimistic 4 * lock (<tt>LockMode.PESSIMISTIC_WRITE</tt>), or to simply reassociate a transient instance 5 * with a session (<tt>LockMode.NONE</tt>). This operation cascades to associated 6 * instances if the association is mapped with <tt>cascade="lock"</tt>. 7 * 8 * @param object a persistent or transient instance 9 * @param lockMode the lock level 10 * 11 * @deprecated instead call buildLockRequest(LockMode).lock(object) 12 */ 13 @Deprecated 14 public void lock(Object object, LockMode lockMode);
根据注释可以知道其有三个职责:
- 执行乐观锁检查,然后执行。
- 提升为悲观锁,然后执行。
- 将一个透明的实例(脱钩)和 Session 进行关联。
注意:1 和 2 都会执行 3。
LockMode.NONE
测试代码
1 package demo; 2 3 import model.*; 4 import org.hibernate.*; 5 6 /* 7 * lock 会将处于 transparent 状态的对象变为 persisted。 8 */ 9 public class LockDemo implements Demo { 10 11 @Override 12 public void run() { 13 SessionHelper.read(new SessionAction() { 14 User user = UserHelper.createUser(); 15 16 @SuppressWarnings("deprecation") 17 @Override 18 public void action(Session session) { 19 session.lock(user, LockMode.NONE); 20 21 // 为了测试执行 lock 后实例是否变为持久化状态。 22 user = (User) session.get(User.class, user.getId()); 23 } 24 25 }); 26 } 27 }
说明:上例执行后没有任何 SQL 输出。
LockMode.READ
测试代码
1 package demo; 2 3 import model.*; 4 import org.hibernate.*; 5 6 /* 7 * lock 会将处于 transparent 状态的对象变为 persisted。 8 */ 9 public class LockDemo implements Demo { 10 11 @Override 12 public void run() { 13 SessionHelper.read(new SessionAction() { 14 User user = UserHelper.createUser(); 15 16 @SuppressWarnings("deprecation") 17 @Override 18 public void action(Session session) { 19 session.lock(user, LockMode.READ); 20 21 // 为了测试执行 lock 后实例是否变为持久化状态。 22 user = (User) session.get(User.class, user.getId()); 23 } 24 25 }); 26 } 27 }
输出结果
1 /* READ lock model.User */ select 2 Id 3 from 4 Users 5 where 6 Id =? 7 and Version =?
说明:上例执行了乐观锁检查,我还没有测试检查失败的场景,估计是会抛出异常。
LockMode.UPGRADE
测试代码
1 package demo; 2 3 import model.*; 4 import org.hibernate.*; 5 6 /* 7 * lock 会将处于 transparent 状态的对象变为 persisted。 8 */ 9 public class LockDemo implements Demo { 10 11 @Override 12 public void run() { 13 SessionHelper.read(new SessionAction() { 14 User user = UserHelper.createUser(); 15 16 @SuppressWarnings("deprecation") 17 @Override 18 public void action(Session session) { 19 session.lock(user, LockMode.UPGRADE); 20 21 // 为了测试执行 lock 后实例是否变为持久化状态。 22 user = (User) session.get(User.class, user.getId()); 23 } 24 25 }); 26 } 27 }
输出结果
1 /* UPGRADE lock model.User */ select 2 Id 3 from 4 Users 5 where 6 Id =? 7 and Version =? for update
说明:上例将对象对应的数据库记录升级为悲观锁,由此可以保证修改的串行化。
Merge
官方注释
1 /** 2 * Copy the state of the given object onto the persistent object with the same 3 * identifier. If there is no persistent instance currently associated with 4 * the session, it will be loaded. Return the persistent instance. If the 5 * given instance is unsaved, save a copy of and return it as a newly persistent 6 * instance. The given instance does not become associated with the session. 7 * This operation cascades to associated instances if the association is mapped 8 * with {@code cascade="merge"} 9 * <p/> 10 * The semantics of this method are defined by JSR-220. 11 * 12 * @param object a detached instance with state to be copied 13 * 14 * @return an updated persistent instance 15 */ 16 public Object merge(Object object);
根据注释可以知道 merge 有两个职责:
- 如果对象为 unsaved,对对象的拷贝执行 save 方法,返回拷贝的对象。
- 如果对象为 detached,将对象的状态拷贝到和对象的标识一样的持久化对象中,如果持久化对象不存在,就执行 get 方法将其加载。
detached 对象测试
测试代码
1 package demo; 2 3 import model.*; 4 import org.hibernate.*; 5 6 /* 7 * merge 不会将参数变为持久化状态,而是使用参数修改 session 中的持久化对象,如果 session 中不包含持久化 8 * 对象,就从数据库中加载一个,如果对象为 unsaved 状态,就对其拷贝执行 save。 9 */ 10 public class MergeDemo implements Demo { 11 12 @Override 13 public void run() { 14 SessionHelper.execute(new SessionAction() { 15 User user = UserHelper.createUser(); 16 17 @Override 18 public void action(Session session) { 19 User newUser = new User(); 20 newUser.setId(user.getId()); 21 newUser.setUsername("shijiucha"); 22 newUser.setPassword(user.getPassword()); 23 newUser.setVersion(user.getVersion()); 24 25 session.merge(newUser); 26 } 27 28 }); 29 } 30 }
输出结果
1 begin transaction 2 action 3 Hibernate: 4 /* load model.User */ select 5 user0_.Id as Id1_2_0_, 6 user0_.Version as Version2_2_0_, 7 user0_.Username as Username3_2_0_, 8 user0_.Password as Password4_2_0_ 9 from 10 Users user0_ 11 where 12 user0_.Id=? 13 flush and commit 14 Hibernate: 15 /* update 16 model.User */ update 17 Users 18 set 19 Version=?, 20 Username=?, 21 Password=? 22 where 23 Id=? 24 and Version=?
说明:上例先执行了 select 语句,然后执行了合并过程,因为有修改,在 flush 的时候产生了 update 语句。
unsaved 对象测试
测试代码
1 package demo; 2 3 import model.*; 4 import org.hibernate.*; 5 6 /* 7 * merge 不会将参数变为持久化状态,而是使用参数修改 session 中的持久化对象,如果 session 中不包含持久化 8 * 对象,就从数据库中加载一个,如果对象为 unsaved 状态,就对其拷贝执行 save。 9 */ 10 public class MergeDemo implements Demo { 11 12 @Override 13 public void run() { 14 SessionHelper.execute(new SessionAction() { 15 User user = UserHelper.createUser(); 16 17 @Override 18 public void action(Session session) { 19 User newUser = new User(); 20 newUser.setId(user.getId()); 21 newUser.setUsername("shijiucha"); 22 newUser.setPassword(user.getPassword()); 23 //newUser.setVersion(user.getVersion()); 24 25 session.merge(newUser); 26 } 27 28 }); 29 } 30 }
输出结果
1 begin transaction 2 action 3 Hibernate: 4 /* insert model.User 5 */ insert 6 into 7 Users 8 (Version, Username, Password) 9 values 10 (?, ?, ?) 11 flush and commit
说明:上例只执行了 insert 语句,因为 user 是 unsaved 状态。
备注
hibernate 的注释写的真是漂亮。
另外说一句:lock 已经被标记为过时了,可是为啥没有提示其替代方法呢?
转载于:https://www.cnblogs.com/happyframework/p/3353261.html
Hibernate:不容易理解的 lock 和 merge相关推荐
- hibernate二级缓存理解
2019独角兽企业重金招聘Python工程师标准>>> 缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对 ...
- Hibernate之深入理解持久化对象
持久化是将程序数据在持久化状态和瞬时状态间转换的机制,持久化类可以被hibernate保存到数据库并且从数据库中读取的类.简而言之,一个对象一旦被持久化了,那么这个对象的某个属性一旦改变了,数据库中的 ...
- hibernate - mappedby的理解
mappedBy的意思就是"被映射",即mappedBy这方不用管关联关系,关联关系交给另一方处理 1.规律:凡是双向关联,mapped必设,因为根本都没必要在2个表中都存在一个外 ...
- mysql select lock in share mode_深入理解SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE
概念和区别 SELECT ... LOCK IN SHARE MODE走的是IS锁(意向共享锁),即在符合条件的rows上都加了共享锁,这样的话,其他session可以读取这些记录,也可以继续添加IS ...
- hibernate面试问题_Hibernate面试问答
hibernate面试问题 Hibernate is one of the most widely used ORM tool for Java applications. It's used a l ...
- HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档
Hibernate参考文档 3.1.2 目录 前言 1. 翻译说明 2. 版权声明 1.Hibernate入门 1.1.前言 1.2.第一部分-第一个Hibernate应用程序 1.2.1.第一个cl ...
- Hibernate 一对一、一对多、多对多注解cascade属性的总结
作用:是否级联被注解字段里面的对象.可选值:javax.persistence.CascadeType.PERSIST, MERGE, REMOVE, REFRESH, DETACH, ALL.可选其 ...
- (转)Hibernate框架基础——cascade属性
http://blog.csdn.net/yerenyuan_pku/article/details/52760010 我们以部门和员工的关系为例讲解一对多关联关系映射时,删除部门时,如果部门有关联的 ...
- Hibernate框架基础——cascade属性
我们以部门和员工的关系为例讲解一对多关联关系映射时,删除部门时,如果部门有关联的员工且inverse属性为false,那么由于可以维护关联关系,它就会先把关联的员工的外键列设为null值,再删除自己. ...
最新文章
- ODBC的多线程应用
- Yii框架里用grid.CGridView调用pager扩展不显示最后一页按钮的解决
- Postgres-XL数据库集群在RedHat/Fedora/Oracle/CentOS平台上的搭建
- XP共享拒绝访问,全面解决
- JS不间断无缝滚动 (兼容火狐和IE)
- 阿里云服务器web项目启动连接mysql_在腾讯云阿里云上部署JavaWeb项目(Tomcat+MySQL)...
- JavaScript的语法规则
- python集合运算_python set集合的基本运算
- 锐捷长ping_【路由】交换卡下的客户端无法ping通网关
- 解决Android Studio连接不到ios模拟器问题
- 简单对抗神经网络GAN实现与讲解-图片对抗
- MEGARAC(宝德)服务器BMC登录失败解决办法
- 华为VLAN隔离配置
- Python+Tushare股票数据分析
- 软件构件技术期末复习
- unity 跨平台动态生成二维码 免费下载
- python爬取百部电影数据,我分析出了一个残酷的真相
- PHP基础篇 php接口interface到底有什么用?
- 计算机桌面出现家庭组,win10系统桌面突然多出一个家庭组图标的修复步骤
- (从完全入门开始)思科模拟器创建校园网,第一次写博客
热门文章
- 什么样的网站结构备受搜索引擎喜爱?
- 提升网站竞争力从这三方面着手努力!
- sub在python中的意义_在python中,如何使用回复sub?
- alert获取输入框内容_实用开源:Web 聊天工具的富文本输入框
- 电大计算机应用基础 课程考核3,电大专科-计算机应用基础作业3答案.doc
- linux 下的dd,Linux中的dd命令
- MySQL用sqoop导出乱码_Sqoop将hive数据导出到MySQL中文乱码了怎么办?
- linux mysql忘记root_linux下mysql-5.6忘记root密码,重置root密码详细过程
- python爬取资料_Python爬取FLASH播放器中的资料
- android从放弃到精通 第九天 勿忘初心