Save()saveOrUpdate()Hibernate的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

2

3

4

5

6

7

8

9

10

11

12

13

14

Session session = this.getSession();  

Transaction tr = session.beginTransaction();  

User exituser = (User)session.get(User.classnew Integer(1));  

exituser.setAge(11);  

session.merge(exituser);  

tr.commit();  

session.close(); 

Session session = this.getSession(); 

Transaction tr = session.beginTransaction(); 

User exituser = (User)session.get(User.classnew Integer(1)); 

exituser.setAge(11); 

session.merge(exituser); 

tr.commit(); 

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-04 15:38:22

Save()saveOrUpdate()Hibernate的merge()方法的相关文章

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

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

[原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

Hibernate Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分别是做什么的?有什么区别?

session的方法: save(): insert 调用save方法之后,瞬时态对象可以变成持久态: update():update 将游离态对象变为持久态 saveOrUpdate():insert or update merge(): merge()方法可以完成save()和update()方法的功能,它的意图是将新的状态合并到已有的持久化对象上或创建新的持久化对象. 将游离态对象变为持久态. lock(): lock()方法是把一个没有更改过的脱管状态的对象变成持久状态. persisi

Hibernate中Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法的区别

Hibernate的对象有三种状态,分别是:瞬时态(transient).持久态(persistent).游离态(detached) 1.瞬时态的实例可以通过调用save().persist()或者saveOrUpdate()方法变成持久态 2.游离态的实例可以通过调用 update().saveOrUpdate().lock()或者replicate()方法变成持久态 3.save()和update()方法的区别在于前者是将瞬时态对象变成持久态,后者是将游离态对象变成持久态 4.merge()

Hibernate各保存方法之间的差 (save,persist,update,saveOrUpdte,merge,flush,lock)等一下

hibernate保存 hibernate要保存的目的是提供一个方法,多.它们之间有许多不同之处,点击此处详细说明.使得差: 一.预赛: 在所有.阐释.供hibernate,,transient.persistent.detached 下边是常见的翻译办法: transient:瞬态或者自由态 persistent:持久化状态 detached:脱管状态或者游离态 脱管状态的实例能够通过调用save().persist()或者saveOrUpdate()方法进行持久化. 持久化实例能够通过调用

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中的merge()方法

Hibernate提供有save().persist().savaOrUpdate()和merge()等方法来提供插入数据的功能.前三者理解起来较后者容易一些,而merge()方法从api中的介绍就可以看出它是最复杂的,因此要特别留意一下. Hibernate的api中关于merge()方法的原文 merge Object merge(Object object) throws HibernateException Copy the state of the given object onto

Hibernate中的merge方法

Hibernate中有一个常见的错误: A different object with the same identifier value was already associated with the session 在一个session中存在两个不同的实体却有着相同的身份标签(主键)是会报错的,想要避免这种错误可以使用Hibernate中的merge方法. merge方法的作用: new一个对象并设置ID时,这个对象会被当作游离态处理,在使用merge时,如果在数据库中不能能找到这条记录,则

Hibernate的merge与update方法的区别

今天做了个测试,写了个测试用例来看看merge与update时控制台打印出来的日志有什么不一样.实体bean很简单,就id和name两个字段,接下来分别给出以下几种测试情形的控制台日志内容: 1. 数据库记录已存在,更改person的name为一个新的name. merge方法打印出的日志如下: Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from person person0_ where person0