EntityManager
EntityManager
The diagram above presents an overview of the EntityManager
interface. For a complete treatment of the
EntityManager API, see the
Javadoc documentation. Methods whose parameter signatures consist of
an ellipsis (...) are overloaded to take multiple parameter types.
OpenJPA extends the standard EntityManager interface with
the
org.apache.openjpa.persistence.OpenJPAEntityManager interface to provide additional functionality.
The EntityManager is the primary interface used by
application developers to interact with the JPA runtime. The methods
of the EntityManager can be divided into the following
functional categories:
Transaction association.
Entity lifecycle management.
Entity identity management.
Cache management.
Query factory.
Closing.
Transaction Association
EntityManager
obtaining the Transaction
transactions
Transaction
obtaining from EntityManager
public EntityTransaction getTransaction ();
Every EntityManager has a one-to-one relation with an
EntityTransaction
instance. In fact, many vendors use a single class to implement both the
EntityManager and EntityTransaction
interfaces. If your application requires multiple concurrent
transactions, you will use multiple EntityManagers.
You can retrieve the EntityTransaction associated with an
EntityManager through the getTransaction
method. Note that most JPA implementations can
integrate with an application server's managed transactions. If you take
advantage of this feature, you will control transactions by declarative
demarcation or through the Java Transaction API (JTA) rather than through the
EntityTransaction.
Entity Lifecycle Management
EntityManager
lifecycle operations
EntityManagers perform several actions that affect the
lifecycle state of entity instances.
public void persist(Object entity);
EntityManager
persist
persist
EntityManager
persistent objects
persisting
Transitions new instances to managed. On the next flush or commit, the newly
persisted instances will be inserted into the datastore.
For a given entity A, the persist
method behaves as follows:
If A is a new entity, it becomes managed.
If A is an existing managed entity, it is ignored. However,
the persist operation cascades as defined below.
If A is a removed entity, it becomes managed.
If A is a detached entity, an
IllegalArgumentException is thrown.
The persist operation recurses on all relation fields of A
whose cascades include
CascadeType.PERSIST.
This action can only be used in the context of an active transaction.
public void remove(Object entity);
EntityManager
remove
remove
EntityManager
persistent objects
deleting
Transitions managed instances to removed. The instances will be deleted from the
datastore on the next flush or commit. Accessing a removed entity has undefined
results.
For a given entity A, the remove
method behaves as follows:
If A is a new entity, it is ignored. However, the remove
operation cascades as defined below.
If A is an existing managed entity, it becomes removed.
If A is a removed entity, it is ignored.
If A is a detached entity, an
IllegalArgumentException is thrown.
The remove operation recurses on all relation fields of A
whose cascades include
CascadeType.REMOVE.
This action can only be used in the context of an active transaction.
public void refresh(Object entity);
EntityManager
refresh
refresh
EntityManager
persistent objects
refreshing state
transactions
optimistic
Use the refresh action to make sure the persistent
state of an instance is synchronized with the values in the datastore.
refresh is intended for long-running optimistic
transactions in which there is a danger of seeing stale data.
For a given entity A, the refresh
method behaves as follows:
If A is a new entity, it is ignored. However, the refresh
operation cascades as defined below.
If A is an existing managed entity, its state is refreshed
from the datastore.
If A is a removed entity, it is ignored.
If A is a detached entity, an
IllegalArgumentException is thrown.
The refresh operation recurses on all relation fields of A
whose cascades include
CascadeType.REFRESH.
public Object merge(Object entity);
EntityManager
merge
detachment
detachment
JPA
merge
detachment
data transfer object
value object
A common use case for an application running in a servlet or application server
is to "detach" objects from all server resources, modify them, and then "attach"
them again. For example, a servlet might store persistent data in a user session
between a modification based on a series of web forms. Between each form
request, the web container might decide to serialize the session, requiring that
the stored persistent state be disassociated from any other resources.
Similarly, a client/server application might transfer persistent objects to a
client via serialization, allow the client to modify their state, and then have
the client return the modified data in order to be saved. This is sometimes
referred to as the data transfer object or value
object pattern, and it allows fine-grained manipulation of data
objects without incurring the overhead of multiple remote method invocations.
JPA provides support for this pattern by automatically detaching
entities when they are serialized or when a persistence context ends (see
for an exploration of
persistence contexts). The JPA merge API
re-attaches detached entities. This allows you to detach a persistent instance,
modify the detached instance offline, and merge the instance back into an
EntityManager (either the same one that detached the
instance, or a new one). The changes will then be applied to the existing
instance from the datastore.
A detached entity maintains its persistent identity, but cannot load additional
state from the datastore. Accessing any persistent field or property that was
not loaded at the time of detachment has undefined results. Also, be sure not to
alter the version or identity fields of detached instances if you plan on
merging them later.
The merge method returns a managed copy of the given
detached entity. Changes made to the persistent state of the detached entity are
applied to this managed instance. Because merging involves changing persistent
state, you can only merge within a transaction.
If you attempt to merge an instance whose representation has changed in the
datastore since detachment, the merge operation will throw an exception, or the
transaction in which you perform the merge will fail on commit, just as if a
normal optimistic conflict were detected.
OpenJPA offers enhancements to JPA detachment functionality,
including additional options to control which fields are detached. See
in the Reference Guide for details.
For a given entity A, the merge
method behaves as follows:
If A is a detached entity, its state is copied into existing
managed instance A' of the same entity identity, or a new
managed copy of A is created.
If A is a new entity, a new managed entity A'
is created and the state of A is copied into
A'.
If A is an existing managed entity, it is ignored. However,
the merge operation still cascades as defined below.
If A is a removed entity, an
IllegalArgumentException is thrown.
The merge operation recurses on all relation fields of A
whose cascades include
CascadeType.MERGE.
public void lock (Object entity, LockModeType mode);
EntityManager
lock
locking
EntityManager
This method locks the given entity using the named mode. The
javax.persistence.LockModeType enum defines two
modes:
READ: Other transactions may concurrently read the object,
but cannot concurrently update it.
WRITE: Other transactions cannot concurrently read or write
the object. When a transaction is committed that holds WRITE locks on any
entities, those entities will have their version incremented even if the entities
themselves did not change in the transaction.
OpenJPA has additional APIs for controlling object locking. See
in the Reference Guide for details.
The following diagram illustrates the lifecycle of an entity with respect to the
APIs presented in this section.
Lifecycle Examples
The examples below demonstrate how to use the lifecycle methods presented in the
previous section. The examples are appropriate for out-of-container use. Within
a container, EntityManagers are usually injected, and
transactions are usually managed. You would therefore omit the
createEntityManager and close calls, as
well as all transaction demarcation code.
Persisting Objects
persistent objects
persisting
example
// create some objects
Magazine mag = new Magazine("1B78-YU9L", "JavaWorld");
Company pub = new Company("Weston House");
pub.setRevenue(1750000D);
mag.setPublisher(pub);
pub.addMagazine(mag);
Article art = new Article("JPA Rules!", "Transparent Object Persistence");
art.addAuthor(new Author("Fred", "Hoyle"));
mag.addArticle(art);
// persist
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(mag);
em.persist(pub);
em.persist(art);
em.getTransaction().commit();
// or we could continue using the EntityManager...
em.close();
Updating Objects
persistent objects
updating
example
Magazine.MagazineId mi = new Magazine.MagazineId();
mi.isbn = "1B78-YU9L";
mi.title = "JavaWorld";
// updates should always be made within transactions; note that
// there is no code explicitly linking the magazine or company
// with the transaction; JPA automatically tracks all changes
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Magazine mag = em.find(Magazine.class, mi);
mag.setPrice(5.99);
Company pub = mag.getPublisher();
pub.setRevenue(1750000D);
em.getTransaction().commit();
// or we could continue using the EntityManager...
em.close();
Removing Objects
persistent objects
deleting
example
// assume we have an object id for the company whose subscriptions
// we want to delete
Object oid = ...;
// deletes should always be made within transactions
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Company pub = (Company) em.find(Company.class, oid);
for (Subscription sub : pub.getSubscriptions())
em.remove(sub);
pub.getSubscriptions().clear();
em.getTransaction().commit();
// or we could continue using the EntityManager...
em.close();
Detaching and Merging
This example demonstrates a common client/server scenario. The client requests
objects and makes changes to them, while the server handles the object lookups
and transactions.
// CLIENT:
// requests an object with a given oid
Record detached = (Record) getFromServer(oid);
...
// SERVER:
// send object to client; object detaches on EM close
Object oid = processClientRequest();
EntityManager em = emf.createEntityManager();
Record record = em.find(Record.class, oid);
em.close();
sendToClient(record);
...
// CLIENT:
// makes some modifications and sends back to server
detached.setSomeField("bar");
sendToServer(detached);
...
// SERVER:
// merges the instance and commit the changes
Record modified = (Record) processClientRequest();
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Record merged = (Record) em.merge(modified);
merged.setLastModified(System.currentTimeMillis());
merged.setModifier(getClientIdentityCode());
em.getTransaction().commit();
em.close();
Entity Identity Management
Each EntityManager is responsible for managing the
persistent identities of the managed objects in the persistence context. The
following methods allow you to interact with the management of persistent
identities. The behavior of these methods is deeply affected by the persistence
context type of the EntityManager; see
for an explanation of
persistence contexts.
public <T> T find(Class<T> cls, Object oid);
EntityManager
find
identity
find
EntityManager
identity
retrieving objects by identity
This method returns the persistent instance of the given type with the given
persistent identity. If the instance is already present in the current
persistence context, the cached version will be returned. Otherwise, a new
instance will be constructed and loaded with state from the datastore. If no
entity with the given type and identity exists in the datastore, this method
returns null.
public <T> T getReference(Class<T> cls, Object oid);
EntityManager
getReference
identity
getReference
EntityManager
identity
retrieving objects by identity
EntityNotFoundException
This method is similar to find, but does not
necessarily go to the database when the entity is not found in cache. The
implementation may construct a hollow entity and return it
to you instead. Hollow entities do not have any state loaded. The state only
gets loaded when you attempt to access a persistent field. At that time, the
implementation may throw an EntityNotFoundException if it
discovers that the entity does not exist in the datastore. The implementation
may also throw an EntityNotFoundException from the
getReference method itself. Unlike
find, getReference does not return null.
public boolean contains(Object entity);
EntityManager
contains
contains
EntityManager
Returns true if the given entity is part of the current persistence context, and
false otherwise. Removed entities are not considered part of the current
persistence context.
Cache Management
EntityManager
cache
public void flush();
EntityManager
flush
flush
EntityManager
transactions
flushing changes before commit
The flush method writes any changes that have been made
in the current transaction to the datastore. If the EntityManager
does not already have a connection to the datastore, it obtains one
for the flush and retains it for the duration of the transaction. Any exceptions
during flush cause the transaction to be marked for rollback. See
.
Flushing requires an active transaction. If there isn't a transaction in
progress, the flush method throws a
TransactionRequiredException.
public FlushModeType getFlushMode();
public void setFlushMode(FlushModeType flushMode);
EntityManager
FlushMode
FlushMode
The EntityManager's FlushMode property
controls whether to flush transactional changes before executing queries. This
allows the query results to take into account changes you have made during the
current transaction. Available
javax.persistence.FlushModeType constants are:
COMMIT: Only flush when committing, or when told to do so
through the flush method. Query results may not take
into account changes made in the current transaction.
AUTO: The implementation is permitted to flush before
queries to ensure that the results reflect the most recent object state.
You can also set the flush mode on individual
Query
instances.
OpenJPA only flushes before a query if the query might be affected by data
changed in the current transaction. Additionally, OpenJPA allows fine-grained
control over flushing behavior. See the Reference Guide's
.
public void clear();
EntityManager
clear
clear
EntityManager
Clearing the EntityManager effectively ends the
persistence context. All entities managed by the EntityManager
become detached.
Query Factory
EntityManager
as Query factory
Query
Query
creating
public Query createQuery(String query);
Query objects are used to find entities matching certain
criteria. The createQuery method creates a query using
the given Java Persistence Query Language (JPQL) string. See
for details.
public Query createNamedQuery(String name);
This method retrieves a query defined in metadata by name. The returned
Query instance is initialized with the information
declared in metadata. For more information on named queries, read
.
public Query createNativeQuery(String sql);
public Query createNativeQuery(String sql, Class resultCls);
public Query createNativeQuery(String sql, String resultMapping);
Native queries are queries in the datastore's native
language. For relational databases, this the Structured Query Language (SQL).
elaborates on JPA's
native query support.
Retrieving Properties Information
EntityManager
properties information
&properties_info.xml;
Closing
EntityManager
closing
public boolean isOpen();
public void close();
When an EntityManager is no longer needed, you should
call its close method. Closing an
EntityManager releases any resources it is using. The persistence
context ends, and the entities managed by the EntityManager
become detached. Any Query instances the
EntityManager created become invalid. Calling any method
other than isOpen on a closed EntityManager
results in an IllegalStateException. You
cannot close a EntityManager that is in the middle of a
transaction.
If you are in a managed environment using injected entity managers, you should
not close them.