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()如果是对一个已经存在的托管对象进行更新那么肯定是要使用 ...
随机推荐
- angular源码分析:angular中jqLite的实现——你可以丢掉jQuery了
一.从function JQLite(element)函数开始. function JQLite(element) { if (element instanceof JQLite) { //情况1 r ...
- form中动态生成Radiobutton控件
public partial class GetLabelFields : Form { int tableCount; public GetLabelFields(AxMapControl axma ...
- html框架—多对话框(相同id)处理
一个网站的数据大多数都是异步刷新的,这没什么好说的,然后现在很多前后端框架,大家都知道框架很好用,不用自己写样式,只要利用框架上的语法就能做出漂亮的动态的效果来,而用框架的话大多数的动态效果都是动态生 ...
- 设置 Xcode 自动生成代码片段
一.什么是代码片段 当在Xcode中输入dowhile并回车后,Xcode会出现下图所示的提示代码: 这就是代码片段,目的是使程序员以最快的速度输入常用的代码片段,提高编程效率.该功能是从Xcode4 ...
- Android 生成xml文件
生成XML文件备份短信,其格式为: <?xml version="1.0" encoding="UTF-8" standalone="true& ...
- android 最简单的自定义圆点view
首先创建一个选择器,用来判断圆点状态,可以根本自己的需求改 <selector xmlns:android="http://schemas.android.com/apk/res/an ...
- iOS Address Book指南
尽管OC是一门面向对象的语言,但是在你做开发的时候你会发现,并不是所有你用的frameworks都是面向对象的.有些是用C写的,例如Address Book的API,接下来让我们去学习一下Addres ...
- OC中的特有语法
一. 分类-Category 1. 基本用途 如何在不改变原来类模型的前提下,给类扩充一些方法?有2种方式 l 继承 l 分类(Category) 2. 格式 分类的声明 @interface 类名 ...
- iOS 杂笔-23(区分各种空值)
iOS 杂笔-23(区分各种空值) nil是一个对象指针为空 Nil是一个类指针为空 NULL是基本数据类型为空 NSNull空对象(是可以放在数组里的)
- Android开机广播
有些时候我们常常需要某个程序开机运行.在这个时候我们就需要监听系统的开机广播,然后启动我们的程序即可. 不多说 直接上代码: public class BootReceiver extends Bro ...