Hibernate: save, persist, update, merge, saveOrUpdate[z]
[z]https://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate
1. Introduction
In this article we will discuss the differences between several methods of the Sessioninterface: save, persist, update, merge, saveOrUpdate.
This is not an introduction to Hibernate and you should already know the basics of configuration, object-relational mapping and working with entity instances. For an introductory article to Hibernate, visit our tutorial on Hibernate 4 with Spring.
Further reading:
Stored Procedures with Hibernate
This article shortly discusses how to call store procedures from Hibernate.
An Overview of Identifiers in Hibernate
Learn how to map entity identifiers with Hibernate.
2. Session as a Persistence Context Implementation
The Session interface has several methods that eventually result in saving data to the database: persist, save, update, merge, saveOrUpdate. To understand the difference between these methods, we must first discuss the purpose of the Session as a persistence context and the difference between the states of entity instances in relation to the Session.
We should also understand the history of Hibernate development that led to some partly duplicated API methods.
2.1. Managing Entity Instances
Apart from object-relational mapping itself, one of the problems that Hibernate was intended to solve is the problem of managing entities during runtime. The notion of “persistence context” is Hibernate’s solution to this problem. Persistence context can be thought of as a container or a first-level cache for all the objects that you loaded or saved to a database during a session.
The session is a logical transaction, which boundaries are defined by your application’s business logic. When you work with the database through a persistence context, and all of your entity instances are attached to this context, you should always have a single instance of entity for every database record that you’ve interacted during the session with.
In Hibernate, the persistence context is represented by org.hibernate.Session instance. For JPA, it is the javax.persistence.EntityManager. When we use Hibernate as a JPA provider and operate via EntityManager interface, the implementation of this interface basically wraps the underlying Session object. However, Hibernate Session provides a richer interface with more possibilities so sometimes it is useful to work with Session directly.
2.2. States of Entity Instances
Any entity instance in your application appears in one of the three main states in relation to the Session persistence context:
- transient — this instance is not, and never was, attached to a Session; this instance has no corresponding rows in the database; it’s usually just a new object that you have created to save to the database;
- persistent — this instance is associated with a unique Session object; upon flushing the Session to the database, this entity is guaranteed to have a corresponding consistent record in the database;
- detached — this instance was once attached to a Session (in a persistent state), but now it’s not; an instance enters this state if you evict it from the context, clear or close the Session, or put the instance through serialization/deserialization process.
Here is a simplified state diagram with comments on Session methods that make the state transitions happen.

When the entity instance is in the persistent state, all changes that you make to the mapped fields of this instance will be applied to the corresponding database records and fields upon flushing the Session. The persistent instance can be thought of as “online”, whereas the detached instance has gone “offline” and is not monitored for changes.
This means that when you change fields of a persistent object, you don’t have to call save, update or any of those methods to get these changes to the database: all you need is to commit the transaction, or flush or close the session, when you’re done with it.
2.3. Conformity to JPA Specification
Hibernate was the most successful Java ORM implementation. No wonder that the specification for Java persistence API (JPA) was heavily influenced by the Hibernate API. Unfortunately, there were also many differences: some major, some more subtle.
To act as an implementation of the JPA standard, Hibernate APIs had to be revised. Several methods were added to Session interface to match the EntityManager interface. These methods serve the same purpose as the “original” methods, but conform to the specification and thus have some differences.
3. Differences Between the Operations
It is important to understand from the beginning that all of the methods (persist, save, update, merge, saveOrUpdate) do not immediately result in the corresponding SQL UPDATEor INSERT statements. The actual saving of data to the database occurs on committing the transaction or flushing the Session.
The mentioned methods basically manage the state of entity instances by transitioning them between different states along the lifecycle.
As an example entity, we will use a simple annotation-mapped entity Person:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
@Entitypublic class Person { @Id @GeneratedValue private Long id; private String name; // ... getters and setters} |
3.1. Persist
The persist method is intended for adding a new entity instance to the persistence context, i.e. transitioning an instance from transient to persistent state.
We usually call it when we want to add a record to the database (persist an entity instance):
|
1
2
3
|
Person person = new Person();person.setName("John");session.persist(person); |
What happens after the persist method is called? The person object has transitioned from transient to persistent state. The object is in the persistence context now, but not yet saved to the database. The generation of INSERT statements will occur only upon commiting the transaction, flushing or closing the session.
Notice that the persist method has void return type. It operates on the passed object “in place”, changing its state. The person variable references the actual persisted object.
This method is a later addition to the Session interface. The main differentiating feature of this method is that it conforms to the JSR-220 specification (EJB persistence). The semantics of this method is strictly defined in the specification, which basically states, that:
- a transient instance becomes persistent (and the operation cascades to all of its relations with cascade=PERSIST or cascade=ALL),
- if an instance is already persistent, then this call has no effect for this particular instance (but it still cascades to its relations with cascade=PERSIST or cascade=ALL),
- if an instance is detached, you should expect an exception, either upon calling this method, or upon committing or flushing the session.
Notice that there is nothing here that concerns the identifier of an instance. The spec does not state that the id will be generated right away, regardless of the id generation strategy. The specification for the persist method allows the implementation to issue statements for generating id on commit or flush, and the id is not guaranteed to be non-null after calling this method, so you should not rely upon it.
You may call this method on an already persistent instance, and nothing happens. But if you try to persist a detached instance, the implementation is bound to throw an exception. In the following example we persist the entity, evict it from the context so it becomes detached, and then try to persist again. The second call to session.persist() causes an exception, so the following code will not work:
|
1
2
3
4
5
6
7
|
Person person = new Person();person.setName("John");session.persist(person);session.evict(person);session.persist(person); // PersistenceException! |
3.2. Save
The save method is an “original” Hibernate method that does not conform to the JPA specification.
Its purpose is basically the same as persist, but it has different implementation details. The documentation for this method strictly states that it persists the instance, “first assigning a generated identifier”. The method is guaranteed to return the Serializable value of this identifier.
|
1
2
3
|
Person person = new Person();person.setName("John");Long id = (Long) session.save(person); |
The effect of saving an already persisted instance is the same as with persist. Difference comes when you try to save a detached instance:
|
1
2
3
4
5
6
|
Person person = new Person();person.setName("John");Long id1 = (Long) session.save(person);session.evict(person);Long id2 = (Long) session.save(person); |
The id2 variable will differ from id1. The call of save on a detached instance creates a new persistent instance and assigns it a new identifier, which results in a duplicate record in a database upon committing or flushing.
3.3. Merge
The main intention of the merge method is to update a persistent entity instance with new field values from a detached entity instance.
For instance, suppose you have a RESTful interface with a method for retrieving an JSON-serialized object by its id to the caller and a method that receives an updated version of this object from the caller. An entity that passed through such serialization/deserialization will appear in a detached state.
After deserializing this entity instance, you need to get a persistent entity instance from a persistence context and update its fields with new values from this detached instance. So the merge method does exactly that:
- finds an entity instance by id taken from the passed object (either an existing entity instance from the persistence context is retrieved, or a new instance loaded from the database);
- copies fields from the passed object to this instance;
- returns newly updated instance.
In the following example we evict (detach) the saved entity from context, change the namefield, and then merge the detached entity.
|
1
2
3
4
5
6
7
8
|
Person person = new Person(); person.setName("John"); session.save(person);session.evict(person);person.setName("Mary");Person mergedPerson = (Person) session.merge(person); |
Note that the merge method returns an object — it is the mergedPerson object that was loaded into persistence context and updated, not the person object that you passed as an argument. Those are two different objects, and the person object usually needs to be discarded (anyway, don’t count on it being attached to persistence context).
As with persist method, the merge method is specified by JSR-220 to have certain semantics that you can rely upon:
- if the entity is detached, it is copied upon an existing persistent entity;
- if the entity is transient, it is copied upon a newly created persistent entity;
- this operation cascades for all relations with cascade=MERGE or cascade=ALL mapping;
- if the entity is persistent, then this method call does not have effect on it (but the cascading still takes place).
3.4. Update
As with persist and save, the update method is an “original” Hibernate method that was present long before the merge method was added. Its semantics differs in several key points:
- it acts upon passed object (its return type is void); the update method transitions the passed object from detached to persistent state;
- this method throws an exception if you pass it a transient entity.
In the following example we save the object, then evict (detach) it from the context, then change its name and call update. Notice that we don’t put the result of the update operation in a separate variable, because the update takes place on the person object itself. Basically we’re reattaching the existing entity instance to the persistence context — something the JPA specification does not allow us to do.
|
1
2
3
4
5
6
7
|
Person person = new Person();person.setName("John");session.save(person);session.evict(person);person.setName("Mary");session.update(person); |
Trying to call update on a transient instance will result in an exception. The following will not work:
|
1
2
3
|
Person person = new Person();person.setName("John");session.update(person); // PersistenceException! |
3.5. SaveOrUpdate
This method appears only in the Hibernate API and does not have its standardized counterpart. Similar to update, it also may be used for reattaching instances.
Actually, the internal DefaultUpdateEventListener class that processes the update method is a subclass of DefaultSaveOrUpdateListener, just overriding some functionality. The main difference of saveOrUpdate method is that it does not throw exception when applied to a transient instance; instead, it makes this transient instance persistent. The following code will persist a newly created instance of Person:
|
1
2
3
|
Person person = new Person();person.setName("John");session.saveOrUpdate(person); |
You may think of this method as a universal tool for making an object persistent regardless of its state wether it is transient or detached.
4. What to Use?
If you don’t have any special requirements, as a rule of thumb, you should stick to the persistand merge methods, because they are standardized and guaranteed to conform to the JPA specification.
They are also portable in case you decide to switch to another persistence provider, but they may sometimes appear not so useful as the “original” Hibernate methods, save, update and saveOrUpdate.
5. Conclusion
We’ve discussed the purpose of different Hibernate Session methods in relation to managing persistent entities in runtime. We’ve learned how these methods transist entity instances through their lifecycles and why some of these methods have duplicated functionality.
The source code for the article is available on GitHub.
Hibernate: save, persist, update, merge, saveOrUpdate[z]的更多相关文章
- hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)等
hibernate的保存hibernate对于对象的保存提供了太多的方法,他们之间有很多不同,这里细说一下,以便区别:一.预备知识:在所有之前,说明一下,对于hibernate,它的对象有三种状态,t ...
- Hibernate各保存方法之间的差 (save,persist,update,saveOrUpdte,merge,flush,lock)等一下
hibernate保存 hibernate要保存的目的是提供一个方法,多.它们之间有许多不同之处,点击此处详细说明.使得差: 一.预赛: 在所有.阐释.供hibernate,,transient.p ...
- hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)
hibernate的保存hibernate对于对象的保存提供了太多的方法,他们之间有很多不同,这里细说一下,以便区别:一.预备知识:在所有之前,说明一下,对于hibernate,它的对象有三种状态,t ...
- 【转】NHIBERNATE的各种保存方式的区别 (SAVE,PERSIST,UPDATE,SAVEORUPDTE,MERGE,FLUSH,LOCK)
前言 今天学学习NH这个框架,在新增对象的时候,看见大神用了persist而没有用Save,心中比较疑惑,查阅资料的时候,发现这篇写的非常不错,转载供大家参考. hibernate的保存hiberna ...
- hibernate中save、update、saveOrUpdate的区别
saveOrUpdate如果hibernate-mapping配置的主键已存在,就不会新增,会更新. ------------------------------------------------- ...
- Hibernate save, saveOrUpdate, persist, merge, update 区别
Hibernate Save hibernate save()方法能够保存实体到数据库,正如方法名称save这个单词所表明的意思.我们能够在事务之外调用这个方法,这也是我不喜欢使用这个方法保存数据的原 ...
- Hibernate中Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法有什么区别?
Hibernate的对象有三种状态:瞬态.持久态和游离态.游离状态的实例可以通过调用save().persist()或者saveOrUpdate()方法进行持久化:脱管状态的实例可以通过调用 upda ...
- Hibernate方法save、update、merge、saveOrUpdate及get和load的区别
在看这几个方法区别之前,有必要了解hibernate实体对象的三种状态,点击查看 http://www.cnblogs.com/Y-S-X/p/8345754.html 一.update 和 merg ...
- Hibernate save()、saveOrUpdate()、merge()的区别
一. update 和 merge的区别 首先在执行更新操作的时候,两者都必须要有id update是直接执行update 语句,执行后状态为持久化状态 而merge则不一样: 1. 如果sessio ...
随机推荐
- 转:用JS获取地址栏参数的方法(超级简单)
转载链接: http://www.cnblogs.com/fishtreeyu/archive/2011/02/27/1966178.html 方法一:采用正则表达式获取地址栏参数:( 强烈推荐,既实 ...
- Android-json解析:原生JSONObject+JSONArray的使用【转】
原文地址:https://blog.csdn.net/sinat_31057219/article/details/71518123 一.JSONObject和JSONArray的数据表示形式 JSO ...
- JAVA程序员常用英语
JAVA程序员常用英语 干程序员这行实在是离不开英语,干程序员是一项很辛苦的工作,要成为一个高水平的程序员尤为艰难.这是因为计算机软件技术更新的速度越来越快,而这些技术大多来源于英语国家,我们在引进这 ...
- 历届试题 对局匹配-(dp)
问题描述 小明喜欢在一个围棋网站上找别人在线对弈.这个网站上所有注册用户都有一个积分,代表他的围棋水平. 小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是K的两名用户匹配在一起.如果两人分差 ...
- python爬取股票信息
import requests from bs4 import BeautifulSoup import traceback import re def getHTMLText(url): try: ...
- 04_web基础(七)之jsp
39.jsp与el表达式引入 JSP:Java Server Pages:Java的服务网页(Java动态网页):=========================================== ...
- 大型运输行业实战_day14_1_webserivce简单入门
1.简单使用 1.1.服务端 1.编写接口 package com.day02.sation.ws; /** * Created by Administrator on 1/12. */ public ...
- hashcode() equals()
介绍一. hashCode()方法和equal()方法的作用其实一样,在Java里都是用来对比两个对象是否相等一致,那么equal()既然已经能实现对比的功能了,为什么还要hashCode()呢? ...
- Java 获取一个字符串中,另一个字符串出现的次数
Java 获取一个字符串中,另一个字符串出现的次数 思想: 1. indexOf到字符串中到第一次出现的索引2. 找到的索引+被找字符串长度,截取字符串3. 计数器++ 代码实现: public cl ...
- node搭建简单的本地服务器
首先要安装node,方法很多,可以去网上找找,可以直接去官网下载安装,新版本的node是自带npm的: 安装好以后,新建一个js文件,名为server.js: let http = require(' ...