A persistence context is a set of entities such that for any persistent
identity there is a unique entity instance. Within a persistence
context, entities are managed. The
EntityManager
controls their lifecycle, and they can access
datastore resources.
When a persistence context ends, previously-managed entities become
detached. A detached entity is no longer under
the control of the EntityManager
, and no longer
has access to datastore resources. We discuss detachment is detail in
Section 8.2, “Entity Lifecycle Management”. For now, it is sufficient
to know that detachment has two obvious consequences:
The detached entity cannot load any additional persistent state.
The EntityManager
will not return the
detached entity from find
, nor will
queries include the detached entity in their results. Instead,
find
method invocations and query
executions that would normally incorporate the detached entity
will create a new managed entity with the same identity.
Note | |
---|---|
Kodo offers several features related to detaching entities. See
Section 11.1, “Detach and Attach” in the Reference Guide.
In particular, Section 11.1.3, “Defining the Detached Object Graph” describes
how to use the |
Injected EntityManager
s use a
transaction persistence context, while
EntityManager
s obtained through the
EntityManagerFactory
have an
extended persistence context. We describe these persistence
context types below.
Under the transaction persistence context model, an
EntityManager
begins a new persistence context
with each transaction, and ends the context when the transaction
commits or rolls back. Within the transaction, entities you
retrieve through the EntityManager
or via
Queries
are managed entities. They
can access datastore resources to lazy-load additional
persistent state as needed, and only one entity may exist for any
persistent identity.
When the transaction completes, all entities lose their
association with the EntityManager
and
become detached. Traversing a persistent field that wasn't
already loaded now has undefined results. And using the
EntityManager
or a Query
to
retrieve additional objects may now create new instances with the
same persistent identities as detached instances.
If you use an EntityManager
with a
transaction persistence context model outside of
an active transaction, each method invocation creates a new
persistence context, performs the method action, and ends the
persistence context. For example, consider using the
EntityManager.find
method outside
of a transaction. The EntityManager
will
create a temporary persistence context, perform the find operation,
end the persistence context, and return the detached result object
to you. A second call with the same id will return a second
detached object.
When the next transaction begins, the EntityManager
will begin a new persistence context, and will again
start returning managed entities. As you'll see in
Chapter 8, EntityManager, you can also merge the
previously-detached entites back into the new persistence context.
Example 7.1. Behavior of Transaction Persistence Context
The following code illustrates the behavior of entites under
an EntityManager
using a transaction
persistence context.
EntityManager em; // Injected ... // Outside a transaction: // Each operation occurs in a separate persistence context and returns // a new detached instance. Magazine mag1 = em.find (Magazine.class, magId); Magazine mag2 = em.find (Magazine.class, magId); assertTrue (mag2 != mag1); ... // Transaction begins: // Within a transaction, a subsequent lookup doesn't return any of the // detached objects. However, two lookups within the same transaction // return the same instanc, because the persistence context spans the // transaction. Magazine mag3 = em.find (Magazine.class, magId); assertTrue (mag3 != mag1 && mag3 != mag2); Magazine mag4 = em.find (Magazine.class (magId); assertTrue (mag4 == mag3); ... // Transaction commits: // Once again, each operation returns a new instance. Magazine mag5 = em.find (Magazine.class, magId); assertTrue (mag5 != mag3);
An EntityManager
using an extended
persistence context maintains the same persistence context for
its entire lifecycle. Whether inside a transaction or not, all
entities returned from the EntityManager
are managed, and the EntityManager
never
creates two entity instances to represent the same persistent
identity. Entities only become detached when you finally close
the EntityManager
(or when they are
serialized).
Example 7.2. Behavior of Extended Persistence Context
The following code illustrates the behavior of entites under
an EntityManager
using an extended
persistence context.
EntityManagerFactory emf = ... EntityManager em = emf.createEntityManager (PersistenceContextType.EXTENDED); // The persistence context is active for the entire life of the EM, so there is // only one entity for a given persistent identity. Magazine mag1 = em.find (Magazine.class, magId); Magazine mag2 = em.find (Magazine.class, magId); assertTrue (mag2 == mag1); em.getTransaction ().begin (); // The same persistence context is active within the transaction. Magazine mag3 = em.find (Magazine.class, magId); assertTrue (mag3 == mag1); Magazine mag4 = em.find (Magazine.class (magId); assertTrue (mag4 == mag1); em.getTransaction.commit (); // When the transaction commits, the instance is still managed. Magazine mag5 = em.find (Magazine.class, magId); assertTrue (mag5 == mag1); // The instance finally becomes detached when the EM closes. em.close ();