Session as a Persistence Context Implementation The Session interface has several methods that eventually result in saving data to the database: 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.
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. 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. In Hibernate, the persistence context is represented by org. For JPA, it is the javax. 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. 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: 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. Unfortunately, there were also many differences: Several methods were added to Session interface to match the EntityManager interface. 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: Persist The persist method is intended for adding a new entity instance to the persistence context, i.
We usually call it when we want to add a record to the database persist an entity instance: 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.
Notice that the persist method has void return type. The person variable references the actual persisted object. This method is a later addition to the Session interface. The semantics of this method is strictly defined in the specification, which basically states, that: 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. Its purpose is basically the same as persist, but it has different implementation details. The method is guaranteed to return the Serializable value of this identifier.
Difference comes when you try to save a detached instance: 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. 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. 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: In the following example we evict detach the saved entity from context, change the name field, and then merge the detached entity. As with persist method, the merge method is specified by JSR to have certain semantics that you can rely upon: Its semantics differs in several key points: In the following example we save the object, then evict detach it from the context, then change its name and call update.
The following will not work: 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: The source code for the article is available on GitHub.