How Does Merge Work in JPA (and Hibernate)

The JPA EntityManager there are the merge() and persist() methods. In hibernate there’s more – save, persist, saveOrUpdate, update, merge. I’m always using merge() for the sake of simplicity, but one must be aware what is the exact behaviour of this method.
I had to read the JPA spec (1.0, but I guess it should be unchanged in 2.0) in order to get the following:

  • if the entity is already in the persistence context (session), no action is taken, except for cascades
  • if the entity is detached, a copy (object’) is returned, which is attached (managed)
  • if the entity is transient (new instance), it is saved and a persistent (and managed) copy is returned
  • if the entity is detached, but an object with the same identifier exist in the current entity manager, then the state of the detached object is copied into the current persistent entity, and it (the current) is returned

Here’s a test that depicts what’s happening:

Message msg = new Message();
 Message msg2 = em.merge(msg);

 System.out.println("New, transient object: " + msg);
 System.out.println("Merged object: " + msg2);

 Message msg3 = em.merge(msg2);

 System.out.println("Merging persistent object: " + msg3);

 Message msg4 = new Message();

 Message msg5 = em.merge(msg4);
 System.out.println("Detached entity with same id: " + msg5);
 System.out.println("Merged text: " + msg5.getText());


 Message msg6 = em.merge(msg5);

 System.out.println("Merged detached entity: " + msg6);

And the resulet is:

New, transient object:
Merged object:
Merging persistent object:
Detached entity with same id:
Merged text: Bar
Hibernate: select as id1_1_, message0_.authorId .....
Merged detached entity:

I haven’t had problems with using merge() only, but one must know what he’s getting.

(Note: The same goes for Hibernate’s merge())

Update: you can read more on the topic here

4 thoughts on “How Does Merge Work in JPA (and Hibernate)”

  1. What about the case where an entity is new (detached) and you set a random (non existing) id on it. Shoulnd’t merge fail with some sort of not found exception, since the id implies that you’re merging changes into an existing entity, and instead there is no entity with that particular id?

  2. I’m not sure. If the ID is autogenerated it might fail, but otherwise it will probably insert it as new.

  3. @Eugen: This is implementation dependent.

    Hibernate uses the ID to determine whether an instance already exists in the database.

    So when you set the ID to 0 or null, merge()/save() will insert a new instance (plus assign a new id). You will end with two different rows in the database.

    If you set the ID, Hibernate will try to update the existing row which will fail.

Leave a Reply

Your email address will not be published.