Hibernate EntityManager | merge() v/s persist() [Part 1]

Hibernate’s entity manager merge and persist provide two different functionalities all together. While persist can make a transient object persistent, merge on the other hand makes a copy of the object passed to it and makes this new copy managed. Read more

In this post, we will deep dive into what persist is and how it works on entities in different states.

Stir until blended

Documentation Say

  • persist() makes a transient instance persistent. However, it does not guarantee that the identifier value will be assigned to the persistent instance immediately, the assignment might happen at flush time.
  • persist() also guarantees that it will not execute an INSERT statement if it is called outside of transaction boundaries. This is useful in long-running conversations with an extended Session/persistence context.

Trying it out

To understand the above, let us go through the following example. Source code available on my github profile.

I have created Product entities and a DAO layer as described below. Please note that I am handholding the transaction management (PersistenceContextType.EXTENDED), so as to ensure that plane vanilla versions of these updates are called and auto transaction management doesn’t mess up anything.

Now, I have three variants of Product entity object, which I am passing to the relevant update methods.

  1. Persist Transient Bean with Id: This will result in the following exception
    Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist:
    This happens because passing a DETACHED instance of an entity having Id as autogenerated, to persist() method is not allowed. (Look for DefaultPersistEventListener source code in hibernate)
  2. Persist Transient Bean without Id: This will result in insertion of the entity into the database underneath.
  3. Persist Persistent Bean: This won’t have ANY affect on the row in the database underneath. The reason being, for a persistent object, persist() only cascades the operations and does nothing else at all.


So if you are handholding transactions properly, never use persist() for any update operation, because it is not meant for them. Always use merge(). In my next post, will try to deep dive into merge() functionality.

Like what you read? Give Arpit Jain a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.