Does JPA's commit() method make entity detached?
Entity can become detached in one of the following ways (there could be more ways):
When the transaction (in transaction-scoped persistence context) commits, entities managed by the persistence context become detached.
If an application-managed persistence context is closed, all managed entities become detached.
Using clear method
using detach method
rollback
In extended persistence context when a stateful bean is removed, all managed entities become detached.
I think the problem could be the difference between application managed, user managed, extended persistence contexts.
This picture is from openjpa but IMO (other opinions are welcome) its a bit wrong?! (In EE with TRANSACTION Scope its okay) But in a JAVA SE Example like this: ....
EntityTransaction et = em.getTransaction();
et.begin();
em.persist(entity);
et.commit();
System.out.println(em.contains(entity)); // true
em.detach(entity);
System.out.println(em.contains(entity)); // false
entity = em.merge(entity);
System.out.println(em.contains(entity)); // true
The entity is detached after detached method. After commit it stays in the entity persistence context.
For your question: when you have a detached object you can use merge to reattach it to the persistence context.
2 things :
the state remove and detached are different :Removed
means that the entity is still managed and will trigger a deletion in persitence layer on the flush, Detached
means that the entity is no longer managed and that the changes made on it won't be reported to database.
Your entity state is related to an entityManager
. Managed
means that the EM
tracks all changes made on it and will report them on database at flush time.
You must understand that reporting changes to the database has no sense outside of a transaction (JPA
support only transacted access to DB and only in isolation level READ_COMMITED
).
Tracking change on the entity once the transaction in which it has been retrieved has expired has so no sense as EntityManager
won't be able to alter database state outside of a transaction.
That's why The EntityManager
in JPA
is designed to be created for each unit of work (contrary to the persistenceUnit, ie. the entityManagerFactory which is created once for the whole application).
In consequence the EntityManager
should have the same scope than the transaction and should be released just after the commit (which is the case when you let the container manage the entityManager lifecycle for you).
That's also the reason why JPA
does not support nested transactions.