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.
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.
- 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) - Persist Transient Bean without Id: This will result in insertion of the entity into the database underneath.
- 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.
Conclusion
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.