JPA remove() a deteched entity: find() vs merge() - Which is better?

Viewed 294

In most examples of removing detached entities, the remove is usually paired with a merge:

em.remove(em.merge(detachedEntity));

My question is why is it not "more correct" to use find:

em.remove(em.find(Entity.class, detachedEntity.id));

or

em.remove(em.find(detachedEntity.getClass(), detachedEntity.id));

Is there a performance benefit over using merge?

2 Answers

In order to use EntityManager.remove() you need a managed entity. If you already have the detached entity, the easiest way is to call merge() to attach it to the persistence context. You could use find, but since the detached entity already contains the necessary information (class and id), there's no need to explicitly specify the class and retrieve the id.

You would only need find() if you didn't have the detached entity in the first place. So it's not "more correct" to use find() in this case, it's "more to type".

It might seem odd if you think of "merge" as "update", but it makes more sense when you think of it as "reattach" which it is in this case (and JPA thinks of it that way too, you often see the wording "merging back to the persistence context" which is not the same as "updating the entity in the DB" even though it may result in that...unless for example remove() is called afterwards).

I would say that the correct way would be a JPQL statement deleting the entity by ID, that way you'll ensure that your database will only receive a DELETE statement and not a (wasteful) SELECT followed by DELETE.

I think you could achieve the same effect by using em.getReference instead of em.find (or merge) if want to avoid JPQL.

You should really check the generated SQL statements. If you see a select followed by a delete statement and your logic doesn't need that select, your code is going to be much slower than necessary. If that happens in a loop, it's going to be abysmally slow.

You can still use find or merge (it doesn't matter which one, it's going to be a SELECT statement after all) followed by remove if your algorithm needs to do something else with other entity attributes before calling remove. In this case there would be no faster way anyway.

Related