一、Save()

save()方法能够保存实体到数据库。假如两个实体之间有关系(例如employee表和address表有一对一关系),如果在没有事务的情况下调用这个方法保存employee这个实体,除非调用flush()这个方法,否则仅仅employee实体会被保存。

二、SaveOrUpdate()

saveOrUpdate()方法会执行插入或者更新操作。如果该对象在数据库中已经存在则更新,不存在则插入。

也可以在没有事务的情况下执行,但是如果没有手动调用flush()方法会面临关联对象不被保存的问题

save()方法与saveOrUpdate()方法最大的不同点在于:saveOrUpdate()方法会将实体对象添加到持久化上下文中,该实体的后续改变会被跟踪。

例子:

package nd.esp.com.hibernate.example;import nd.esp.com.hibernate.model.Address;
import nd.esp.com.hibernate.model.Employee;
import nd.esp.com.hibernate.utils.HibernateUtil;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;public class HibernateSaveOrUpdateExample {public static void main(String[] args) {// Prep WorkSessionFactory sessionFactory = HibernateUtil.getSessionFactory();System.out.println("***********************************************");// saveOrUpdate example - without transactionSession session5 = sessionFactory.openSession();Employee emp5 = getTestEmployee();session5.saveOrUpdate(emp5);System.out.println("***********************************************");// saveOrUpdate example - with transactionSession session3 = sessionFactory.openSession();Transaction tx3 = session3.beginTransaction();Employee emp3 = getTestEmployee();session3.saveOrUpdate(emp3);emp3.setName("Kumar"); // will be saved into DBSystem.out.println("9. Before committing saveOrUpdate transaction. Id=" + emp3.getId());tx3.commit();System.out.println("10. After committing saveOrUpdate transaction");System.out.println("***********************************************");Transaction tx4 = session3.beginTransaction();emp3.setName("Updated Test Name"); // Name changedemp3.getAddress().setCity("Updated City");session3.saveOrUpdate(emp3);emp3.setName("Kumar"); // again changed to previous value, so no Employee updateSystem.out.println("11. Before committing saveOrUpdate transaction. Id=" + emp3.getId());tx4.commit();System.out.println("12. After committing saveOrUpdate transaction");System.out.println("***********************************************");// Close resources
        sessionFactory.close();}public static Employee getTestEmployee() {Employee emp = new Employee();Address add = new Address();emp.setName("Test Emp");add.setCity("Test City");emp.setAddress(add);add.setEmployee(emp);return emp;}
}

执行代码,输出结果:

***********************************************
Hibernate: insert into EMPLOYEE (emp_name) values (?)
***********************************************
Hibernate: insert into EMPLOYEE (emp_name) values (?)
9. Before committing saveOrUpdate transaction. Id=21
Hibernate: insert into ADDRESS (city, emp_id) values (?, ?)
Hibernate: update EMPLOYEE set emp_name=? where emp_id=?
10. After committing saveOrUpdate transaction
***********************************************
11. Before committing saveOrUpdate transaction. Id=21
Hibernate: update ADDRESS set city=? where emp_id=?
12. After committing saveOrUpdate transaction
***********************************************

注意:如果没有事务,仅仅是employee实体被保存到数据库,而address的信息丢失了。

在事务tx4中的几行代码employee实体的name属性先被修改为“Updated Test Name”,之后又被赋值为原来的值“Kumar”,因此employee这个实体在事务提交之前并没有改变,所以并没有update操作。

三、Merge()

如果某对象处于游离态,游离态是指该对象的id值为空。hibernate判断一个对象在数据库中是否存在不是看对象的其他信息,而是判断该id在数据库中是不是存在。如果id为空,那自然是不存在,所以当我们调用merge方法的时候,就会直接执行插入操作。这一点有点像saveorupdate()方法。

Object merge(Object object)throws HibernateException
Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade="merge"
The semantics of this method are defined by JSR-220.
Parameters:
object - a detached instance with state to be copied
Returns:
an updated persistent instance
Throws:
HibernateException

首先从参数说明来看,merge的参数应该是一个处于托管状态的实例对象,而返回值则是一个持久化对象。但是这里的参数并不是一定要是托管状态的对象,它还可以是瞬态和持久化的实例对象。正因如此,才使merge方法变得复杂化。

经代码检验从merge方法产生的效果来看,它和saveOrUpdate方法相似,因此虽然上面提到是因为参数状态的不同造成复杂化,但是这里我并不打算分参数的不同状态来理解merge,而是根据参数有无id或id是否已经存在来理解merge。个人认为这样更容易理解,而且从执行他们两个方法而产生的sql语句来看是一样的。

1. 参数实例对象没有提供id或提供的id在数据库中不存在:这时merge将执行插入操作,产生的sql语句如下,

Hibernate: select max(uid) from user

Hibernate: insert into hibernate1.user (name, age, uid) values (?, ?, ?)

2. 参数实例对象的id在数据库中已经存在,此时又有两种情况:

(1)如果对象有改动,则执行更新操作,产生sql语句有,

Hibernate: select user0_.uid as uid0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from hibernate1.user user0_ where user0_.uid=? 
         Hibernate: update hibernate1.user set name=?, age=? where uid=?

(2)如果对象为改动,则执行查询操作,产生的语句有,

Hibernate: select user0_.uid as uid0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from hibernate1.user user0_ where user0_.uid=?

不管哪种情况,merge的返回值都是一个持久化的实例对象,但对于参数而言不会改变它的状态。

虽然从功能上merge方法与saveOrUpdate类似,但他们仍有区别。现在有这样一种情况:我们先通过session的get方法得到一个对象u,然后关掉session,再打开一个session并执行saveOrUpdate(u)。此时我们可以看到抛出异常:Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session,即在session缓存中不允许有两个id相同的对象。不过若使用merge方法则不会异常,其实从merge的中文意思(合并)我们就可以理解了。

转载于:https://www.cnblogs.com/WJ-163/p/5827018.html

save()、saveOrUpdate()、merge()的区别相关推荐

  1. save(),saveOrUpdate(),merge()的区别

    save(),saveOrUpdate(),merge()的区别 Save save()方法能够保存实体到数据库,正如方法名称save这个单词所表明的意思.我们能够在事务之外调用这个方法,这也是我不喜 ...

  2. Hibernate save, saveOrUpdate, persist, merge, update 区别

    Hibernate save, saveOrUpdate, persist, merge, update 区别 - 小黑客 - 博客园 https://www.cnblogs.com/xiaoheik ...

  3. Hibernate三种状态的区分,以及save,update,saveOrUpdate,merge等的使用

    Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object ...

  4. Hibernate中saveOrUpdate()和merge()的区别

    this.getSession().merge(obj);this.getSession().saveOrUpdate(obj); saveOrUpdate(): saveOrUpdate()基本上就 ...

  5. Hibernate中保存与持久性以及saveOrUpdate之间的区别

    保存与保存或更新与持久保存在Hibernate中 save和saveOrUpdate之间的区别是什么或save和persist之间的区别是任何Hibernate面试中常见的面试问题,就像Hiberna ...

  6. Hibernate 中upate,savaOrUpdate,merge的区别

    通常下面的场景会使用update()或saveOrUpdate(): 程序在第一个session中加载对象 该对象被传递到表现层 对象发生了一些改动 该对象被返回到业务逻辑层 程序调用第二个sessi ...

  7. Git rebase 和 Git merge 的区别,你知道吗?

    编辑搜图 请点击输入图片描述 Git是大多数程序必备的工具之一,Git常用那么几个命令:pull.push.status.merge.rebase.Git rebase 和 Git merge都是合并 ...

  8. npm 中 --save 与 --save-dev 的区别

    前言 在使用 npm 安装模块包的时候使用 npm install 模块名称 命令.但通常后面会加上 --save 或者 --save-dev,那么这两个命令有什么区别昵?以下是四种安装方式.以 we ...

  9. git merge\git merge --no-commit\git merge --squash区别

    假设现有分支develop.test.需要将test合并到develop分支. 首先git checkout develop. git merge test test分支会合并到develop,会有t ...

最新文章

  1. 使用正则表达式进行高效的测试
  2. 近期活动盘点:高管AI大数据能力研修班、英伟达初创企业展示开启报名
  3. 参加浙江中医药大学第十一届程序设计竞赛(ACM赛制)的总结
  4. Java多线程知识小抄集(一)
  5. 剑指 Offer 57 - II. 和为s的连续正数序列 思考分析
  6. [编程技巧] C++字符串初始化的优化写法
  7. 链表的常见操作(转)
  8. MongoDB 我的学习笔记
  9. python装饰器@
  10. 【Flutter】微信项目实战【06】 通讯录界面搭建(中)
  11. python找不同数字的个数_在Python中找到N个按位或等于K的不同数字
  12. java过滤器验证app用户token_SpringCloud笔记之Zuul过滤器PreFilter实现token校验(简单样例)...
  13. python pyhook_python中使用pyhook实现键盘监控的例子
  14. P3369普通平衡树
  15. win10共享文件夹“您没有权限访问,请与网络管理员联系请求访问权限”解决方案
  16. 【SAP Abap】记录一次完整的BDC录屏开发
  17. 最短路问题的线性规划模型
  18. 阿里妈妈佣金转换API接口
  19. HTML复习笔记——CSS排版
  20. python gui是什么_python gui是什么?

热门文章

  1. 软件套装 推荐书籍-海洋工程类
  2. 查看linux服务器下接设备,linux下如何查看设备信息_网站服务器运行维护
  3. mysql中的竖线怎么用_Mysql event时间触发器,实现定时修改某些符合某一条件的某一字段...
  4. redis订阅执行一段时间自动停止_面试系列 redis 分布式锁amp;数据一致性
  5. python编辑公式_分分钟甩Word几条街,Python编辑公式竟可以如此简单
  6. 三坐标测量圆直径_RationalDMIS 7.1 如何准确测量圆/圆弧直径
  7. 最长递增子序列Python解法
  8. c语言串口通信_stm32 串口通信收发说明
  9. android hide方法 末班,android 如何引用@hide(隐藏)的类,方法和常量?
  10. cvs数据导入工具 oracle_为中国企业打造的研发项目管理工具ONES Project已支持Jira数据导入...