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

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

Save

save()方法能够保存实体到数据库,正如方法名称save这个单词所表明的意思。我们能够在事务之外调用这个方法,这也是我不喜欢使用这个方法保存数据的原因。假如两个实体之间有关系(例如employee表和address表有一对一关系),如果在没有事务的情况下调用这个方法保存employee这个实体,除非调用flush()这个方法,否则仅仅employee实体会被保存。

saveOrUpdate

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

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

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

HibernateSaveOrUpdateExample.java

以下是简单的hibernate程序,演示saveOrUpdate()方法的使用。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

/*

 * @(#)HibernateSaveOrUpdateExample.java    Created on 2016年4月10日

 * Copyright (c) 2016. All rights reserved.

 */

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;

    }

}

  

执行上述示例程序,输出结果。


1

2

3

4

5

6

7

8

9

10

11

12

13

***********************************************

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操作。

Hibernate的merge()方法

HibernateSQL

下面来讲讲Hibernate的merge方法。我打算按照hibernate对象生命周期的三个状态来讲。

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

再看hibernate的sql语句:

二:脱管态:如果我们把上面代码里//user.setId(4);的注释去掉,那么它就变成了脱管的对象了(其实从游离到脱管就这么简单,没有官方说的那么邪乎...)。这是我们再来看控制台的sql打印:

看到没有,因为id不为空了,所以hibernate就不会再insert了。由于该对象的信息和数据库里的一模一样,所以hibernate只执行了一个select语句,并没有update,如果我们把字段的值做稍微的变动,那么控制台打印的sql语句还应该有一条update语句。就这一点来说,merge还有和saveorupdate()方法一样。

三:持久态:持久态更好理解。如果我们从数据库里get一条记录,那么这条记录就处于持久态,如果再调用merge,那么hibernate就会先判断该记录是否被修改,没有则什么也不干,修改了就update。这一点还是和saveorupdate()有点像。

  1. Session session = this.getSession();
  2. Transaction tr = session.beginTransaction();
  3. User exituser = (User)session.get(User.class, new Integer(1));
  4. exituser.setAge(11);
  5. session.merge(exituser);
  6. tr.commit();
  7. session.close();
  1. Session session = this.getSession();
  2. Transaction tr = session.beginTransaction();
  3. User exituser = (User)session.get(User.class, new Integer(1));
  4. exituser.setAge(11);
  5. session.merge(exituser);
  6. tr.commit();
  7. session.close();

再看控制台打印结果:

如果没有对记录进行修改则不会有后面的那条update语句。

那么merge和saveorupdate()到底有什么区别呢?看一段代码:

运行上面的代码,hibernate给我们报了一个错误:a different object with the same identifier value was already associated with the session。意思是,在session缓存中以两个标识相同的对象,这是不可以的。那么,吧update改成merge会怎么样呢?改为merge后,一切OK,运行正常。其实merge在执行更新之前会将两个标识符相同的对象进行合并,具体合并的方向是向exituser2合并。

时间: 2024-10-15 21:00:57

save(),saveOrUpdate(),merge()的区别的相关文章

Hibernate save()、saveOrUpdate()、merge()的区别

一. update 和 merge的区别 首先在执行更新操作的时候,两者都必须要有id update是直接执行update 语句,执行后状态为持久化状态 而merge则不一样: 1. 如果session中有与之对应的对象,也就是主键相同,则会把要保存的obj的值copy给session中的对象,然后update被复制后的session中的对象 2. 如果session中没有,则会先从数据库中select,然后把obj给查出来的对象copy,则update查出来的对象. 3. 所以merge会先s

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

Hibernate save, saveOrUpdate, persist, merge, update 区别 - 小黑客 - 博客园https://www.cnblogs.com/xiaoheike/p/5374613.html Hibernate save()与persist()区别 - 山楂树男孩的博客专栏 - CSDN博客https://blog.csdn.net/u010739551/article/details/47253881 hibernate中save,update,save

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

Hibernate三种状态的区分,以及save,update,saveOrUpdate,merge等的使用 Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object),瞬时对象和脱管对象也称为VO(Value Object). 瞬时态         由new命令开辟内存空间的java对象, eg. Person person = new Person(

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

Hibernate三种状态的区分,以及save,update,saveOrUpdate,merge等的使用 Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object),瞬时对象和脱管对象也称为VO(Value Object). 瞬时态         由new命令开辟内存空间的java对象, eg. Person person = new Person(

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

Hibernate中saveOrUpdate()和merge()的区别 this.getSession().merge(obj); this.getSession().saveOrUpdate(obj); saveOrUpdate(): saveOrUpdate()基本上就是合成了save()和update() 1.如果该po对象已经在本session中持久化了,在本session中执行saveOrUpdate不做任何事 2.如果savaOrUpdate(新po)与另一个与本session关联的

Hibernate三种状态的区分,以及save,update,saveOrUpdate,merge等的使用 引自http://www.blogjava.net/TiGERTiAN/archive/2008/10/25/236519.html

Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object),瞬时对象和脱管对象也称为VO(Value Object). 瞬时态         由new命令开辟内存空间的java对象, eg. Person person = new Person("xxx", "xx"); 如果没有变量对该对象进行引用,它将被java虚拟机

hibernate中 saveorupdate(),save(),update(),merge()你是怎么看待的;

接触到mybatis竟然有把hibernate抛弃的想法. 言归正传,贴图为先.hibernate的三种状态位和切换之间对函数的使用: 总结下saveorupdate(),save(),update(),merge()这几个函数: save(),update():都是很好理解的 save()在数据库中生成一条记录,如果数据库中有,会报错说有重复的记录. update()就是更新数据库中的记录: merge()就非常奇葩: 1.如果session中存在相同持久化标识(identifier)的实例,

save(),saveorupdate()还有marqe()

所有这三个方法,也就是save().saveOrUpdate()和persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别.例如,save()只能INSERT记录,但是saveOrUpdate()可以进行记录的INSERT和UPDATE.还有,save()的返回值是一个Serializable对象,而persist()方法返回值为void. save与saveOrUpdate的区别 save通过INSERT语句将对象保存到数据库,产生一个新的ID,将数据插入到数据库,并返回一个

Git: 聊聊Rebase命令,与Merge的区别

转帖自2015-12-02 lazybios 日拱一卒 相比Merge命令,大家对Rebase要相对陌生一些,Rebase这个命令在<Pro Git book>中被翻译为「衍合」,感觉好别扭,个人感觉无论是从音还是行(为)叫做「变基」要更佳恰当一些. Rebase的大致流程 Step1: 场景假定 你基于一个远程分支origin创建了一个mywork的分支 git checkout -b mywork origin Step2: 进行开发 创建好分支后,你就开始兢兢业业的在mywork分支上开