In hibernate entities can be in any of these states .
-
New (transient): an entity is new if it has just been instantiated using the new operator, and it is not associated with a persistence context. It has not persisted representation in the database and no identifier value has been assigned.
-
Managed (persistent): a managed entity instance is an instance with a persistent identity that is currently associated with a persistence context.
-
Detached: the entity instance is an instance with a persistent identity that is not associated with a persistence context, usually because the persistence context was closed or the instance was evicted from the context.
-
Removed: a removed entity instance is an instance with a persistent identity, associated with a persistence context, but scheduled for removal from the database.
Hibernate can only work with Managed entities in order to manipulate their state and transfer those actions to the base through SQL, otherwise it will not allow you, therefore a Detached entity that is outside the persistent context can not be persisted or modified in the base, for this you must return your entity back to the persist context and convert your entity Detached to Managed.
In your case the entity 'book' that arrives as parameter the method has been disassociated from the persistence context therefore it is not being managed (detached) by it, that is the reason why it does not allow you to delete it.
When doing
em.find(Notification.class, notification.getId())
You are making a new query to the database by obtaining a new entity, in this case if it is inside the persistence context and for that reason it allows you to delete it.
when doing
em.merge(libro); // libro pasa al persistence context y se convierte en un managed entity
em.remove(libro);
You are adding the detached entity (book) 'book' to the persistence context using the .merge () method, therefore this entity Disassociated (Detached) now becomes managed (Managed), for that reason you can now delete.
Now in your next example, this snippet of code.
em.merge(em.find(Notification.class, notification.getId()));
em.remove(em.find(Notification.class, notification.getId()));
you can simplify it as
Notificacion notificacion = em.find(Notification.class, notification.getId());
em.remove(notificacion);
However this to SQL translates to the following.
SELECT * FROM notificacion WHERE id = :id
DELETE FROM notificacion WHERE id = :id
The first select is necessary in hibernate since this way you get the managed entity (Managed) to be able to eliminate it later with em.remove, but if you only need the ID to be able to delete an entity in SQL then technically the first select is a waste.
Another way to eliminate a disassociated entity is like this.
Libro entity = getEntityManager().getReference(Libro.class, libro.getId());
getEntityManager().remove(entity);
In this case, getReference creates a proxy entity and does not load the status (data) of the database book. (You can only call the set methods of this proxy object).
This is much better since by not loading the database data this only makes the delete and not the first select .
DELETE FROM libro WHERE id = :id