save()、saveOrUpdate()、merge()的区别
一、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 Work
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
System.out.println("***********************************************");
// saveOrUpdate example - without transaction
Session session5 = sessionFactory.openSession();
Employee emp5 = getTestEmployee();
session5.saveOrUpdate(emp5);
System.out.println("***********************************************"); // saveOrUpdate example - with transaction
Session session3 = sessionFactory.openSession();
Transaction tx3 = session3.beginTransaction();
Employee emp3 = getTestEmployee();
session3.saveOrUpdate(emp3);
emp3.setName("Kumar"); // will be saved into DB
System.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 changed
emp3.getAddress().setCity("Updated City");
session3.saveOrUpdate(emp3);
emp3.setName("Kumar"); // again changed to previous value, so no Employee update
System.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的中文意思(合并)我们就可以理解了。
save()、saveOrUpdate()、merge()的区别的更多相关文章
- save(),saveOrUpdate(),merge()的区别
Save save()方法能够保存实体到数据库,正如方法名称save这个单词所表明的意思.我们能够在事务之外调用这个方法,这也是我不喜欢使用这个方法保存数据的原因.假如两个实体之间有关系(例如empl ...
- Hibernate里save(),saveOrUpdate(),merge(),update()的区别
save()方法用于将一个临时对象转变为持久化对象,也就是将一个新的业务实体保存到数据库中:update()方法用于将一个游离对象重新转变为持久化对象,也就是更新一个已经存在的业务实体到数据库中:sa ...
- Hibernate save()、saveOrUpdate()、merge()的区别
一. update 和 merge的区别 首先在执行更新操作的时候,两者都必须要有id update是直接执行update 语句,执行后状态为持久化状态 而merge则不一样: 1. 如果sessio ...
- Hibernate三种状态的区分,以及save,update,saveOrUpdate,merge等的使用 引自http://www.blogjava.net/TiGERTiAN/archive/2008/10/25/236519.html
Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object ...
- hibernate中load,get;find,iterator;merge,saveOrUpdate,lock的区别
hibernate中load,get;find,iterator;merge,saveOrUpdate,lock的区别 转自http://www.blogjava.net/bnlovebn/archi ...
- Hibernate三种状态的区分,以及save,update,saveOrUpdate,merge等的使用
Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object ...
- 论Sava(),SaveOrUpdate(),Merge()区别
一.Save(): 用于将一个临时对象转变为持久化对象,也就是将一个新的业务实体保存到数据库中:相当于jdbc的insert. <假如两个实体之间有关系(例如employee表和address表 ...
- save(),saveorupdate()还有marqe()
所有这三个方法,也就是save().saveOrUpdate()和persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别.例如,save()只能INSERT记录,但是saveOrU ...
- save与 merge与 saveOrUpdate的区别
save()方法很显然是执行保存操作的,如果是对一个新的刚new出来的对象进行保存,自然要使用这个方法了,数据库中没有这个对象. update()如果是对一个已经存在的托管对象进行更新那么肯定是要使用 ...
随机推荐
- Office 365 – SharePoint 2013 Online 与Office相关的应用
1.在Office 365首页,点击在PC上安装Office,如下图: 2.会下载一个安装向导程序,如下图: 3.安装Office向导,如下图: 4.安装完毕以后,发现开始菜单多出Office 201 ...
- Office 365 - SharePoint 2013 Online 中使用Windows PowerShell
1.如果想要在SharePoint Online中使用Windows PowerShell,首先需要安装SharePoint Online Management Shell(下载地址附后),如下图: ...
- [转]很详细的devexpress应用案例
很详细的devexpress应用案例,留着以后参考. 注:转载自http://***/zh-CN/App/Feature.aspx?AppId=50021 UPMS(User Permissions ...
- 源码详解openfire保存消息记录_修改服务端方式
实现openfire消息记录通常有两种方式,修改服务端和添加消息记录插件. 今天,简单的说明一下修改服务端方式实现消息记录保存功能. 实现思路 修改前: 默认的,openfire只提供保存离线记录至o ...
- CALayer 易混淆的两个属性 - position和anchorPoint
1.简单介绍 CALayer有2个非常重要的属性:position和anchorPoint @property CGPoint position; ...
- Android存储访问及目录
Android存储访问及目录 Android的外部存储 Android支持外部存储(case-insensitive filesystem with immutable POSIX permissio ...
- 你真的了解UINavigationController吗?
一:首先查看一下关于UINavigationController的定义 NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationController : ...
- mac 终端 常用指令
开始正式研究ios 应用开发,由于是从C开始学起,所以学习下常用的mac终端指令,方便后续常用操作. mac 终端 常用指令: 1.ls指令 用途:列出文件 常用参数 -w 以简洁的形式列出所有文件和 ...
- uniqid函数产生唯一id,减少碰撞几率
$uuid = str_replace(".","",uniqid(mt_rand(100000,999999),true)); //基于当前时间微妙数,与mt ...
- 史上最详细“截图”搭建Hexo博客并部署到Github
http://jingyan.baidu.com/article/d8072ac47aca0fec95cefd2d.html 大家也搭建过博客,很多时候,按着教程来做就可以了,但是我当时为了搭建Hex ...