JPA detach and immediate merge causes errors

1.2k views Asked by At

I am using JPA (with Hibernate as the JPA provider). I have an operation to remove an entity, and it seems that if I detach the entity and immediately merge it an exception is thrown, i.e.

em.find(entity.class, entitiy.getId())
em.detach(entity)
em.merge(entity)   

will cause errors while simply

em.find(entity.class, entitiy.getId())

Will pass flawlessly. Is there something that I am missing regarding detach and merge? I didn't do anything on the entity itself, it wasn't change, so the merge should not change anything.

I can elaborate more on my specific case if needed.

EDIT

As @rmertins pointed out, I should have used the return value from the merge, as merge returns the merge entity while the entity we have used as a parameter stays detached. This works:

em.find(entity.class, entitiy.getId())
em.detach(entity)
entity = em.merge(entity)  
2

There are 2 answers

1
Rene M. On BEST ANSWER

Sorry my fault, was to fast.

Look here, very good explanation:

http://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-detached-entities/

Here is the sentence that matters:

That means that after invoking EntityManager.merge, we have to use the entity reference returned from that method in place of the original object passed in.

So the clue is that after merge your entity object is still detached, but the resulting object copy from merge is attached to the persistence context again.

0
Vlad Mihalcea On

Is it that you still use the old entity reference instead of the one returned by merge?

The merge operation doesn't reattach the given entity. The merge operation looks for an already loaded entity and since it cannot find one (because you detached it) it loads the entity from the database and it copies the supplied entity data onto the fresh copy from the database.

If you do something like this:

MyEntity myEntity = em.find(MyEntity.class, myEntity.getId())
em.detach(myEntity);
em.merge(myEntity);

Then you simply discard the actual merged entity because you don't reassign myEntity to the merge result. You should do this instead:

myEntity = em.merge(myEntity);

Now myEntity will reference an attached entity (an entity loaded in the 1st Level Cache a.k.a Persistence Context).