This blog article is part of a “series of blog articles” about common pitfalls using JPA and ways to avoid them. In this article, we describe a common error when using EntityManager.merge.
The EnityManager interface provides a method
merge to merge the state of a detached entity into the current persistence context.
The following lines of code show an error prone usage pattern of the
Department dept = ... // detached Department instance em.merge(dept); dept.setFirstname("New name");
Please note, the code ignores the instance being returned by the
merge method. It returns the managed instance the state was merged to. There are two cases:
- The current persistence context does not include an entity with the id of the instance passed to the
mergecall. Then the instance is stored into the persistence context and returned by the
- The current persistence context already has an entity with the id of the instance passed to the
mergecall. The state of the passed instance is merged into the existing entity. The method
mergereturns the existing entity. That means the instance passed as an argument is still in the detached state.
The correct code used the return instance for any other changes:
Department dept = ... // detached Department instance dept = em.merge(dept); dept.setFirstname("New name");
The above error is very tricky, because it depends on the state of the current persistence context. Furthermore, it does not throw an exception in the error case, instead the update statement changes the detached instance, so nothing get store in the database.
Recommendation: Always use the return value of
You can find an example of this pitfall and its solution in the class DuplicatesInQueryResultExperiment in this project: https://github.com/akquinet/jpapitfalls.git.