>>分享孙卫琴的Java技术专稿和著作 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 14979 个阅读者 刷新本主题
 * 贴子主题:  【持久化专题】EntityManager和Session的merge()方法详解 回复文章 点赞(0)  收藏  
作者:sunweiqin    发表时间:2021-05-05 07:53:54     消息  查看  搜索  好友  邮件  复制  引用

本文参考《精通JPA与Hibernate:Java对象持久化技术详解》,作者:孙卫琴,清华大学出版社出版

   JPA API 的EntityManager 以及Hibernate API的Session都有一个merge()方法,它们的作用相同,能够把一个游离对象的属性复制到一个持久化对象中。

当Session用update()方法关联一个游离对象时,如果在持久化缓存中已经存在一个同类型的并且OID相同的持久化对象,那么update()方法会抛出NonUniqueObjectException:
customer1.setName("Jack");//假定customer1为游离对象,OID为1
Session session=sessionFactory.openSession();
tx = session.getTransaction();
tx.begin(); //开始一个事务
//session加载OID为1的Customer持久化对象
Customer customer2=session.get(Customer.class, Long.valueOf(1));

//把OID为1的customer1游离对象加入到持久化缓存中
session.update(customer1);  

//抛出NonUniqueObjectException
tx.commit();
session.close();

下面的代码把update()方法改为merge()方法:

customer1.setName("Jack");//假定customer1为游离对象,OID为1
Session session=sessionFactory.openSession();
tx = session.getTransaction();
tx.begin(); //开始一个事务

//session加载OID为1的Customer持久化对象
Customer customer2=session.get(Customer.class, Long.valueOf(1));

//把customer1对象的属性复制到持久化缓存中的相应持久化对象中
Customer customer3=(Customer)session.merge(customer1);  
customer1==customer2; //false
customer1==customer3; //false
customer2==customer3; //true

//执行update语句,把CUSTOMERS表中ID为1记录的NAME字段改为Jack
tx.commit();
session.close();
return customer3;

Session的merge()方法的处理流程如下:
(1)根据customer1游离对象的OID到持久化缓存中查找匹配的持久化对象。在本例中,找到了匹配的customer2持久化对象,就把customer1游离对象的属性复制到customer2持久化对象中,计划执行一条update语句,再返回customer2持久化对象的引用,所以表达式“customer2==customer3”的值为true。

(2)如果在持久化缓存中没有找到与customer1游离对象的OID一致的Customer持久化对象,那么就试图根据这个OID从数据库中加载Customer持久化对象。如果在数据库中存在这样的Customer持久化对象,就把customer1游离对象的属性复制到这个刚加载的Customer持久化对象中,计划执行一条update语句,再返回这个Customer持久化对象的引用。如果在数据库中不存在这样的Customer持久化对象,就会创建一个新的Customer对象,把customer1游离对象的属性复制到这个新建的Customer对象中,再调用save()方法持久化这个Customer对象,最后返回这个Customer持久化对象的引用。

(3)如果merge()方法的参数customer1为一个临时对象,那么也会创建一个新的Customer对象,把customer1临时对象的属性复制到这个新建的Customer对象中,再调用save()方法持久化这个Customer对象,最后返回这个Customer持久化对象的引用。

从merge()方法的处理流程可以看出,merge()方法返回的customer3是一个持久化对象。参数传入的customer1为游离对象或临时对象,customer1的属性被复制到custome3持久化对象中。程序调用完merge()方法,customer1对象就没有使用价值,可以结束生命周期了,程序接下来可以继续操纵customer3对象。

merge()方法到底把customer1对象的哪些属性复制到customer3持久化对象中呢?主要包括以下内容:

(1)customer1对象的所有值类型的属性。

(2)customer1对象的集合类型属性中的元素。例如,假定customer1对象的orders集合属性中存放了Order对象,以下代码先对orders集合做添加及删除操作。那么merge()方法会对customer3持久化对象的orders集合属性也做相应的添加及删除操作。

customer1.getOrders().add(order1); //加入一个订单
customer1.getOrders().remove(order2); //删除一个订单……
Customer customer3=(Customer)session.merge(customer1);

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

            

----------------------------
原文链接:https://blog.51cto.com/sunweiqin/2752662

程序猿的技术大观园:www.javathinker.net





[这个贴子最后由 admin 在 2021-10-09 10:44:41 重新编辑]
  Java面向对象编程-->内部类
  JavaWeb开发-->使用过滤器
  JSP与Hibernate开发-->数据库事务的并发问题的解决方案
  Java网络编程-->RMI框架
  精通Spring-->Vue CLI脚手架工具
  Vue3开发-->Vue指令
  【Vue.js技术专题】Vue组件的单向数据流
  【Vue.js技术专题】路由导航中抓取数据
  【Vue.js技术专题】在Vue项目中使用Axios
  【Vue.js技术专题】Vuex中异步操作
  【Spring Cloud Alibaba专题】Dubbo框架中提供者回调消费者
  【Java基础编程专题】使用和创建JavaDoc文档
  探讨IT技术作者的素养
  【持久化专题】映射对象标识符的基本原理
  【持久化专题】@Access注解设定Hibernate访问类的属性的方式
  【Java网络编程专题】用Apache HttpClients下载网上的图片等...
  【Java网络编程专题】盘点用Java抓取HTTP服务器和FTP服务器的...
  【Java网络编程专题】用Java套接字访问HTTP服务器读取网页数...
  【JavaWeb专题】Spring MVC创建Web应用范例,轻松入门
  《大话Java程序设计从入门到精通》写作花絮
  我的计算机书籍创作心得
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。