Hibernate Session merge,update,save,saveOrUpdate,persist

Hibernate Session是java应用程序和hibernate框架之间的接口。今天我们将研究Session在表中保存和更新数据的重要方法 - savesaveOrUpdatepersistupdatemerge

目录[ 隐藏 ]

  • 1休眠会话

    • 1.1 Hibernate Session保存
    • 1.2 Hibernate持续存在
    • 1.3 Hibernate saveOrUpdate
    • 1.4 Hibernate更新
    • 1.5 Hibernate Merge

Hibernate Session

Hibernate Session Save

正如方法名称所示,hibernate save()可用于将实体保存到数据库。我们可以在事务外部调用此方法,这就是为什么我不喜欢这种方法来保存数据。如果我们在没有事务的情况下使用它,并且我们在实体之间进行级联,那么除非我们刷新会话,否则只保存主实体。

为了我们的测试目的,我们有两个实体bean - EmployeeAddress


package com.journaldev.hibernate.model;import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;import org.hibernate.annotations.Cascade;@Entity
@Table(name = "EMPLOYEE")
@Access(value=AccessType.FIELD)
public class Employee {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "emp_id")private long id;@Column(name = "emp_name")private String name;@Column(name = "emp_salary")private double salary;@OneToOne(mappedBy = "employee")@Cascade(value = org.hibernate.annotations.CascadeType.ALL)private Address address;//Getter setter methods@Overridepublic String toString() {return "Id= " + id + ", Name= " + name + ", Salary= " + salary+ ", {Address= " + address + "}";}}

package com.journaldev.hibernate.model;import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;@Entity
@Table(name = "ADDRESS")
@Access(value=AccessType.FIELD)
public class Address {@Id@Column(name = "emp_id", unique = true, nullable = false)@GeneratedValue(generator = "gen")@GenericGenerator(name = "gen", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") })private long id;@Column(name = "address_line1")private String addressLine1;@Column(name = "zipcode")private String zipcode;@Column(name = "city")private String city;@OneToOne@PrimaryKeyJoinColumnprivate Employee employee;//Getter setter methods@Overridepublic String toString() {return "AddressLine1= " + addressLine1 + ", City=" + city+ ", Zipcode=" + zipcode;}
}

这是一个简单的hibernate程序,我们save()在不同的情况下调用方法。


package com.journaldev.hibernate.main;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;import com.journaldev.hibernate.model.Address;
import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;public class HibernateSaveExample {public static void main(String[] args) {// Prep WorkSessionFactory sessionFactory = HibernateUtil.getSessionFactory();//save example - without transactionSession session = sessionFactory.openSession();Employee emp = getTestEmployee();long id = (Long) session.save(emp);System.out.println("1. Employee save called without transaction, id="+id);session.flush(); //address will not get saved without thisSystem.out.println("*****");//save example - with transactionTransaction tx1 = session.beginTransaction();Session session1 = sessionFactory.openSession();Employee emp1 = getTestEmployee();long id1 = (Long) session1.save(emp1);System.out.println("2. Employee save called with transaction, id="+id1);System.out.println("3. Before committing save transaction");tx1.commit();System.out.println("4. After committing save transaction");System.out.println("*****");//save example - existing row in tableSession session6 = sessionFactory.openSession();Transaction tx6 = session6.beginTransaction();Employee emp6 =  (Employee) session6.load(Employee.class, new Long(20));//update some dataSystem.out.println("Employee Details="+emp6);emp6.setName("New Name");emp6.getAddress().setCity("New City");long id6 = (Long) session6.save(emp6);emp6.setName("New Name1"); // will get updated in databaseSystem.out.println("5. Employee save called with transaction, id="+id6);System.out.println("6. Before committing save transaction");tx6.commit();System.out.println("7. After committing save transaction");System.out.println("*****");// Close resourcessessionFactory.close();}public static Employee getTestEmployee() {Employee emp = new Employee();Address add = new Address();emp.setName("Test Emp");emp.setSalary(1000);add.setAddressLine1("Test address1");add.setCity("Test City");add.setZipcode("12121");emp.setAddress(add);add.setEmployee(emp);return emp;}
}

当我们执行上面的程序时,它产生以下输出。


Hibernate: insert into EMPLOYEE (emp_name, emp_salary) values (?, ?)
1. Employee save called without transaction, id=149
Hibernate: insert into ADDRESS (address_line1, city, zipcode, emp_id) values (?, ?, ?, ?)
*****
Hibernate: insert into EMPLOYEE (emp_name, emp_salary) values (?, ?)
2. Employee save called with transaction, id=150
3. Before committing save transaction
Hibernate: insert into ADDRESS (address_line1, city, zipcode, emp_id) values (?, ?, ?, ?)
4. After committing save transaction
*****
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee Details=Id= 20, Name= Kumar1, Salary= 1000.0, {Address= AddressLine1= Test address1, City=Blr, Zipcode=12121}
5. Employee save called with transaction, id=20
6. Before committing save transaction
Hibernate: update EMPLOYEE set emp_name=?, emp_salary=? where emp_id=?
Hibernate: update ADDRESS set address_line1=?, city=?, zipcode=? where emp_id=?
7. After committing save transaction
*****

我们可以从上面的输出中确认的几个要点是:

  • 我们应该避免保存外部事务边界,否则将不会保存映射实体导致数据不一致。忘记刷新会话是很正常的,因为它不会抛出任何异常或警告。
  • Hibernate save方法立即返回生成的id,这是可能的,因为一旦调用了save方法,就会保存主对象。
  • 如果从主对象映射了其他对象,则会在提交事务或刷新会话时保存它们。
  • 对于处于持久状态的对象,save通过更新查询更新数据。请注意,它在事务提交时发生。如果对象没有更改,则不会触发任何查询。如果您将多次运行上面的程序,您会注意到下次不会触发更新查询,因为列值没有变化。
  • Hibernate将加载实体对象保存到持久化上下文,如果在保存调用之后但在提交事务之前更新对象属性,则将其保存到数据库中。

Hibernate Persist

Hibernate persist类似于save(with transaction),它将实体对象添加到持久化上下文中,因此跟踪任何进一步的更改。如果在提交事务或刷新会话之前更改了对象属性,则它也将保存到数据库中。

第二个区别是我们persist()只能在事务的边界内使用方法,因此它是安全的并且可以处理任何级联对象。

最后,persist不返回任何内容,因此我们需要使用持久化对象来获取生成的标识符值。让我们看看hibernate坚持使用一个简单的程序。


package com.journaldev.hibernate.main;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;public class HibernatePersistExample {public static void main(String[] args) {// Prep WorkSessionFactory sessionFactory = HibernateUtil.getSessionFactory();    //persist example - with transactionSession session2 = sessionFactory.openSession();Transaction tx2 = session2.beginTransaction();Employee emp2 = HibernateSaveExample.getTestEmployee();session2.persist(emp2);System.out.println("Persist called");emp2.setName("Kumar"); // will be updated in database tooSystem.out.println("Employee Name updated");System.out.println("8. Employee persist called with transaction, id="+emp2.getId()+", address id="+emp2.getAddress().getId());tx2.commit();System.out.println("*****");// Close resourcessessionFactory.close();}}

上述代码产生的输出是:


Hibernate: insert into EMPLOYEE (emp_name, emp_salary) values (?, ?)
8. Employee persist called with transaction, id=158, address id=158
Hibernate: insert into ADDRESS (address_line1, city, zipcode, emp_id) values (?, ?, ?, ?)
Hibernate: update EMPLOYEE set emp_name=?, emp_salary=? where emp_id=?
*****

请注意,插入了第一个雇员对象,然后在事务提交时,执行更新查询以更新名称值。映射的对象地址也保存到数据库中。

Hibernate saveOrUpdate

Hibernate saveOrUpdate根据提供的数据生成插入或更新查询。如果数据存在于数据库中,则执行更新查询。

我们也可以在saveOrUpdate()没有事务的情况下使用,但是如果没有刷新会话,你将再次遇到未被保存的映射对象的问题。

Hibernate saveOrUpdate将实体对象添加到持久上下文并跟踪任何进一步的更改。在提交事务时保存任何进一步的更改,如persist。


package com.journaldev.hibernate.main;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;public class HibernateSaveOrUpdateExample {public static void main(String[] args) {// Prep WorkSessionFactory sessionFactory = HibernateUtil.getSessionFactory();//saveOrUpdate example - without transactionSession session5 = sessionFactory.openSession();Employee emp5 = HibernateSaveExample.getTestEmployee();session5.saveOrUpdate(emp5);System.out.println("*****");//saveOrUpdate example - with transactionSession session3 = sessionFactory.openSession();Transaction tx3 = session3.beginTransaction();Employee emp3 = HibernateSaveExample.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 resourcessessionFactory.close();}
}

以上程序产生以下输出。


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

请注意,没有事务,只会保存Employee并丢失地址信息。

随着事务员工对象被跟踪任何更改,这就是为什么在最后一次调用中,即使在两者之间更改了值,Employee表中也没有更新,最终值保持不变。

Hibernate update

当我们知道我们只更新实体信息时,应该使用Hibernate更新。此操作将实体对象添加到持久上下文,并在提交事务时跟踪和保存进一步的更改。让我们用一个简单的程序检查这个行为。


package com.journaldev.hibernate.main;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;public class HibernateUpdateExample {public static void main(String[] args) {// Prep WorkSessionFactory sessionFactory = HibernateUtil.getSessionFactory();Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();Employee emp = (Employee) session.load(Employee.class, new Long(101));System.out.println("Employee object loaded. " + emp);tx.commit();// update exampleemp.setName("Updated name");emp.getAddress().setCity("Bangalore");Transaction tx7 = session.beginTransaction();session.update(emp);emp.setName("Final updated name");System.out.println("13. Before committing update transaction");tx7.commit();System.out.println("14. After committing update transaction");// Close resourcessessionFactory.close();}}

当我们第一次执行上面的程序时,我们得到以下输出。


Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee object loaded. Id= 101, Name= Test Emp, Salary= 1000.0, {Address= AddressLine1= Test address1, City=Test City, Zipcode=12121}
13. Before committing update transaction
Hibernate: update EMPLOYEE set emp_name=?, emp_salary=? where emp_id=?
Hibernate: update ADDRESS set address_line1=?, city=?, zipcode=? where emp_id=?
14. After committing update transaction

在进一步执行时,我们得到以下输出。


Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee object loaded. Id= 101, Name= Final updated name, Salary= 1000.0, {Address= AddressLine1= Test address1, City=Bangalore, Zipcode=12121}
13. Before committing update transaction
14. After committing update transaction

请注意,首次执行后没有触发更新,因为值中没有更新。另请注意,员工姓名是我们在调用update()方法后设置的“最终更新名称”。这确认了hibernate正在跟踪对象的任何更改,并且在提交事务时,此值已保存。

Hibernate Merge

Hibernate merge可用于更新现有值,但此方法从传递的实体对象创建副本并返回它。返回的对象是持久化上下文的一部分,并跟踪任何更改,不跟踪传递的对象。这是与所有其他方法的merge()的主要区别。让我们用一个简单的程序来看看这个。


package com.journaldev.hibernate.main;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;public class HibernateMergeExample {public static void main(String[] args) {// Prep WorkSessionFactory sessionFactory = HibernateUtil.getSessionFactory();Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();Employee emp = (Employee) session.load(Employee.class, new Long(101));System.out.println("Employee object loaded. " + emp);tx.commit();//merge example - data already present in tablesemp.setSalary(25000);Transaction tx8 = session.beginTransaction();Employee emp4 = (Employee) session.merge(emp);System.out.println(emp4 == emp); // returns falseemp.setName("Test");emp4.setName("Kumar");System.out.println("15. Before committing merge transaction");tx8.commit();System.out.println("16. After committing merge transaction");// Close resourcessessionFactory.close();}}

第一次执行的输出是:


Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee object loaded. Id= 101, Name= Final updated name, Salary= 1000.0, {Address= AddressLine1= Test address1, City=Bangalore, Zipcode=12121}
false
15. Before committing merge transaction
Hibernate: update EMPLOYEE set emp_name=?, emp_salary=? where emp_id=?
16. After committing merge transaction

在进一步执行中,产生的输出是:


Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee object loaded. Id= 101, Name= Kumar, Salary= 25000.0, {Address= AddressLine1= Test address1, City=Bangalore, Zipcode=12121}
false
15. Before committing merge transaction
16. After committing merge transaction

请注意,merge()返回的实体对象与传递的实体不同。另请注意,在进一步执行中,name是“Kumar”,这是因为跟踪返回的对象是否有任何更改。

这就是Hibernate会话 saveupdate方法的全部内容,我希望上面的例子可以帮助您澄清任何疑问。

转载来源:https://www.journaldev.com/3481/hibernate-session-merge-vs-update-save-saveorupdate-persist-example

Hibernate Session merge,update,save,saveOrUpdate,persist相关推荐

  1. Hibernate之Session merge与update方法

    2019独角兽企业重金招聘Python工程师标准>>> 项目中使用Hibernate时报了一个异常:org.hibernate.NonUniqueObjectException;经从 ...

  2. 石油团队赛热身赛----问题 A: Magic Mirror,问题 I: Save the Room,问题 G: Give Candies

    黑色的飞鸟掠过天空,我站在城中,看时间燃成灰烬,哗哗作响...... 问题 A: Magic Mirror 题目描述 Jessie has a magic mirror. Every morning ...

  3. sql语句(select,create,drop,alter,delete,insert,update,grant)

    SQL语言 关系型数据库常见对象 数据库:database 表:table 行:row 列:column 索引:index 视图:view 用户:user 权限:privilege SQL语言规范 S ...

  4. Hibernate Session合并,更新,保存,saveOrUpdate,持久化示例

    Hibernate Session is the interface between java application and hibernate framework. Today we will l ...

  5. hibernate在saveOrUpdate时,update报错:a different object with the same identifier value was already assoc

    1 原因:网上说是,在hibernate中同一个session里面有了两个相同标识但是是不同实体. 2 我找出的解决方法是: getSession().clear(); //在dao层把session ...

  6. django 一对多的添加记录create 和save 方法,update 更新和save()方法的区别,查询API的方法...

    查询api的方法: 表.objects.all() ---[obj1,obj2,....] 表.objects.all().first() 表.objects.filter(id=2) ---[obj ...

  7. Hibernate Session中的save(),update(),delete(),saveOrUpdate() 细粒度分析

    Hibernate在对资料库进行操作之前,必须先取得Session实例,相当于JDBC在对资料库操作之前,必须先取得Connection实例, Session是Hibernate操作的基础,它不是设计 ...

  8. [原创]java WEB学习笔记86:Hibernate学习之路-- -映射 n-n 关系,单向n-n,双向n-n

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

  9. Hibernate api 之常见的类(配置类,会话工厂类,会话类)

    1:Configuration :配置管理类对象 1.1:config.configure(): 加载主配置文件的方法(hibernate.cfg.xml) ,默认加载src/hibernate.cf ...

最新文章

  1. Centos7常用操作
  2. python 字符编码的两种方式写法:# coding=utf-8和# -*- coding:utf-8 -*-
  3. linux 下 etc常用配置信息
  4. 自定义应用Crash时系统显示的对话框
  5. 「2019纪中集训Day7」解题报告
  6. activiti 文档_免费、开源、多平台的PDF文档处理软件——PDFsam Basic
  7. jenkins触发构建后一直重复构建
  8. angular要多久学会_成为优秀Angular开发者所需要学习的19件事
  9. php网站源码怎么在本地电脑调式,Windows 平台下配置ZendStudio调式PHP
  10. Rust: 为什么同样的情况,有时不需要解引用?
  11. s3c2410多通道adc驱动及测试程序(使用write控制多通道)
  12. 矩阵理论第一章-特征值与特征向量
  13. NTC热敏电阻温度计算以及C语言实现
  14. Basic开发笔记:Basic语言介绍、环境搭建、基本语法示例与程序实例
  15. 解决win10+Ubuntu20.0.4双系统,win10时间错误问题
  16. python 苹果李子橙_分享|苹果和它千万不能放在一起!因为它们会……
  17. AWS SAA 认证考试心得
  18. VTCP QIO技术解析
  19. html 淡入淡出效果,css3 transition实现淡入淡出效果 - 小俊学习网
  20. 商业插画是什么?怎么学习商业插画?

热门文章

  1. K均值聚类关于初始聚类中心选取的一种改进(python程序)
  2. matlab读取xls、xlsx、csv文件
  3. 如何用Pygame写游戏(一)
  4. Oracle删除用户与删除表
  5. 【AI视野·今日CV 计算机视觉论文速览 第218期】Fri, 11 Jun 2021
  6. Kubernetes-命名空间token(十五)
  7. 【算法学习】线性时间排序-计数排序、基数排序和桶排序详解与编程实现
  8. sqlserver无法连接到服务器的常见原因和解决办法
  9. 字节缓冲流 BufferedOutputStream java
  10. django-cbv与fbv