A detached entity may result:
from transaction commit if a transaction-scoped container-managed entity manager is used;
from transaction rollback;
from clearing the persistence context;
from closing an entity manager;
and from serializing an entity or otherwise passing an entity by value - e.g., to a separate application tier, through a remote interface, etc.
Detached entity instances continue to live outside of the persistence context in which they were persisted or retrieved, and their state is NO longer guaranteed to be synchronized with the database state.
The application may access the available state of available detached entity instances after the persistence context ends. The available state includes:
Any persistent field or property NOT MARKED fetch=LAZY.
Any persistent field or property that was accessed by the application.
If the persistent field or property is an association, the available state of an associated instance MAY ONLY be safely accessed if the associated instance is available. The available instances include:
Any entity instance retrieved using find().
Any entity instances retrieved using a query or explicitly requested in a FETCH JOIN clause.
Any entity instance for which an instance variable holding non-primary-key persistent state was accessed by the application.
Any entity instance that may be reached from another available instance by navigating associations marked fetch=EAGER.
Merging Detached Entity State
The merge operation allows for the propagation of state from detached entities onto persistent entities managed by the EntityManager.
The semantics of the merge operation applied to an entity X are as follows:
If X is a DETACHED entity, the state of X is COPIED onto a pre-existing managed entity instance X' of the same identity or a NEW MANAGED copy X' of X is created.
If X is a NEW entity instance, a NEW MANAGED entity instance X' is created and the state of X is copied into the NEW MANAGED entity instance X'.
If X is a REMOVED entity instance, an IllegalArgumentException will be thrown by the merge operation (or the transaction commit will fail).
If X is a MANAGED entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities referenced by relationships from X if these relationships have been annotated with the cascade element value cascade=MERGE or cascade=ALL annotation.
For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL, Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed then X is the same object as X'.)
If X is an entity merged to X', with a reference to another entity Y, where cascade=MERGE or cascade=ALL is not specified, then navigation of the same association from X' yields a reference to a managed object Y' with the same persistent identity as Y.
The persistence provider MUST NOT merge fields marked LAZY that have not been fetched: it MUST IGNORE such fields when merging.
Any Version columns used by the entity MUST BE CHECKED by the persistence runtime implementation during the merge operation and/or at flush or commit time. In the absence of Version columns there is no additional version checking done by the persistence provider runtime during the merge operation.
Detached Entities and Lazy Loading
Serializing entities and merging those entities back into a persistence context may not be interoperable across vendors when lazy properties or fields and/or relationships are used.
A vendor is required to support the serialization and subsequent deserialization and merging of detached entity instances (which may contain lazy properties or fields and/or relationships that have not been fetched) back into a separate JVM instance of that vendor's runtime, where both runtime instances have access to the entity classes and any required vendor persistence implementation classes.
When interoperability across vendors is required, the application must not use lazy loading.
It is the responsibility of the application to insure that an instance is managed in only a single persistence context. The behavior is undefined if the same Java instance is made managed in more than one persistence context.
The contains() method can be used to determine whether an entity instance is managed in the current persistence context.
The contains method returns true:
If the entity has been retrieved from the database, and has NOT been removed or detached.
If the entity instance is new, and the persist method has been called on the entity or the persist operation has been cascaded to it.
The contains method returns false:
If the instance is detached.
If the remove method has been called on the entity, or the remove operation has been cascaded to it.
If the instance is new, and the persist method HAS NOT been called on the entity or the persist operation has not been cascaded to it.
Note that the effect of the cascading of persist or remove is IMMEDIATELY visible to the contains method, whereas the ACTUAL insertion or deletion of the database representation for the entity may be DEFERRED until the end of the transaction.