How Does Merge Work in JPA (and Hibernate)

October 22, 2010

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();
 msg.setText("Foo");
 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();
 msg4.setText("Bar");
 msg4.setId(msg3.getId());

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

 em.clear();

 Message msg6 = em.merge(msg5);

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

And the resulet is:

New, transient object: com.foo.model.Message@1f
Merged object: com.foo.model.Message@8da6fe83
Merging persistent object: com.foo.model.Message@8da6fe83
Detached entity with same id: com.foo.model.Message@8da6fe83
Merged text: Bar
Hibernate: select message0_.id as id1_1_, message0_.authorId .....
Merged detached entity: com.foo.model.Message@a13fade8

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())

If you find the content interesting, you can subscribe and get updates


 

3 Responses to “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?
    Thanks.

  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