Managing Entities
Entities are managed by the entity manager. The entity manager is represented by
javax.persistence.EntityManager
instances. EachEntityManager
instance is associated with a persistence context. A persistence context defines the scope under which particular entity instances are created, persisted, and removed.The Persistence Context
A persistence context is a set of managed entity instances that exist in a particular data store. The
EntityManager
interface defines the methods that are used to interact with the persistence context.The EntityManager
The
EntityManager
API creates and removes persistent entity instances, finds entities by the entity's primary key, and allows queries to be run on entities.Container-Managed Entity Managers
With a container-managed entity manager, an
EntityManager
instance's persistence context is automatically propagated by the container to all application components that use theEntityManager
instance within a single Java Transaction Architecture (JTA) transaction.JTA transactions usually involve calls across application components. To complete a JTA transaction, these components usually need access to a single persistence context. This occurs when an
EntityManager
is injected into the application components via thejavax.persistence.PersistenceContext
annotation. The persistence context is automatically propagated with the current JTA transaction, andEntityManager
references that are mapped to the same persistence unit provide access to the persistence context within that transaction. By automatically propagating the persistence context, application components don't need to pass references toEntityManager
instances to each other in order to make changes within a single transaction. The Java EE container manages the lifecycle of container-managed entity managers.To obtain an
EntityManager
instance, inject the entity manager into the application component:Application-Managed Entity Managers
With application-managed entity managers, on the other hand, the persistence context is not propagated to application components, and the lifecycle of
EntityManager
instances is managed by the application.Application-managed entity managers are used when applications need to access a persistence context that is not propagated with the JTA transaction across
EntityManager
instances in a particular persistence unit. In this case, eachEntityManager
creates a new, isolated persistence context. TheEntityManager
, and its associated persistence context, is created and destroyed explicitly by the application.Applications create
EntityManager
instances in this case by using thecreateEntityManager
method ofjavax.persistence.EntityManagerFactory
.To obtain an
EntityManager
instance, you first must obtain anEntityManagerFactory
instance by injecting it into the application component via thejavax.persistence.PersistenceUnit
annotation:Then, obtain an
EntityManager
from theEntityManagerFactory
instance:Finding Entities Using the EntityManager
The
EntityManager.find
method is used to look up entities in the data store by the entity's primary key.@PersistenceContext EntityManager em; public void enterOrder(int custID, Order newOrder) { Customer cust = em.find(Customer.class, custID); cust.getOrders().add(newOrder); newOrder.setCustomer(cust); }Managing an Entity Instance's Lifecycle
You manage entity instances by invoking operations on the entity via an
EntityManager
instance. Entity instances are in one of four states: new, managed, detached, or removed.New entity instances have no persistent identity and are not yet associated with a persistence context.
Managed entity instances have a persistent identity and are associated with a persistence context.
Detached entity instances have a persistent identify and are not currently associated with a persistence context.
Removed entity instances have a persistent identity, are associated with a persistent context, and are scheduled for removal from the data store.
Persisting Entity Instances
New entity instances become managed and persistent by invoking its
persist
method. This means the entity's data is stored to the database when the transaction associated with thepersist
operation is completed. If the entity is already managed, thepersist
operation is ignored. Ifpersist
is called on a removed entity instance, it becomes managed. If the entity is detached,persist
will throw anIllegalArgumentException
, or the transaction commit will fail.@PersistenceContext EntityManager em; ... public LineItem createLineItem(Order order, Product product, int quantity) { LineItem li = new LineItem(order, product, quantity); order.getLineItems().add(li); em.persist(li); return li; }The
persist
operation is propagated to all entities related to the calling entity that have thecascade
element set toALL
orPERSIST
in the relationship annotation.@OneToMany(cascade=ALL, mappedBy="order") public Collection<LineItem> getLineItems() { return lineItems; }Removing Entity Instances
Managed entity instances are removed by invoking its
remove
method, or by a cascadingremove
operation invoked from related entities that have thecascade=REMOVE
orcascade=ALL
elements set in the relationship annotation. If theremove
method is invoked on a new entity, theremove
operation is ignored, although remove will cascade to related entities that have thecascade
element set toREMOVE
orALL
in the relationship annotation. Ifremove
is invoked on a detached entity it will throw anIllegalArgumentException
, or the transaction commit will fail. Ifremove
is invoked on an already removed entity, it will be ignored. The entity's data will be removed from the data store when the transaction is completed, or as a result of theflush
operation.public void removeOrder(Integer orderId) { try { Order order = em.find(Order.class, orderId); em.remove(order); }...In this example, all
LineItem
entities associated with the order are also removed, asOrder.getLineItems
hascascade=ALL
set in the relationship annotation.Synchronizing Entity Data to the Database
The state of persistent entities is synchronized to the database when the transaction with which the entity is associated commits. If a managed entity is in a bidirectional relationship with another managed entity, the data will be persisted based on the owning side of the relationship.
To force synchronization of the managed entity to the data store, invoke the
flush
method of the entity. If the entity is related to another entity, and the relationship annotation has thecascade
element set toPERSIST
orALL
, the related entity's data will be synchronized with the data store whenflush
is called.If the entity is removed, calling
flush
will remove the entity data from the data store.Creating Queries
The
EntityManager.createQuery
andEntityManager.createNamedQuery
methods are used to query the datastore using Java Persistence query language queries. See Chapter 24 for more information on the query language.The
createQuery
method is used to create dynamic queries, queries that are defined directly within an application's business logic.public List findWithName(String name) { return em.createQuery( "SELECT c FROM Customer c WHERE c.name LIKE :custName") .setParameter("custName", name) .setMaxResults(10) .getResultList(); }The
createNamedQuery
method is used to create static queries, queries that are defined in metadata using thejavax.persistence.NamedQuery
annotation. Thename
element of@NamedQuery
specifies the name of the query that will be used with thecreateNamedQuery
method. Thequery
element of@NamedQuery
is the query.@NamedQuery( name="findAllCustomersWithName", query="SELECT c FROM Customer c WHERE c.name LIKE :custName" )Here's an example of
createNamedQuery
, which uses the@NamedQuery
defined above.@PersistenceContext public EntityManager em; ... customers = em.createNamedQuery("findAllCustomersWithName") .setParameter("custName", "Smith") .getResultList();Named Parameters in Queries
Named parameters are parameters in a query that are prefixed with a colon (
:
). Named parameters in a query are bound to an argument by thejavax.persistence.Query.setParameter(String name, Object value)
method. In the following example, thename
argument to thefindWithName
business method is bound to the:custName
named parameter in the query by callingQuery.setParameter
.public List findWithName(String name) { return em.createQuery( "SELECT c FROM Customer c WHERE c.name LIKE :custName") .setParameter("custName", name) .getResultList(); }Named parameters are case-sensitive, and may be used by both dynamic and static queries.
Positional Parameters in Queries
You may alternately use positional parameters in queries, instead of named parameters. Positional parameters are prefixed with a question mark (
?
) followed the numeric position of the parameter in the query. TheQuery.setParameter(integer position, Object value)
method is used to set the parameter values.In the following example, the
findWithName
business method is rewritten to use input parameters:public List findWithName(String name) { return em.createQuery( "SELECT c FROM Customer c WHERE c.name LIKE ?1") .setParameter(1, name) .getResultList(); }Input parameters are numbered starting from 1. Input parameters are case-sensitive, and may be used by both dynamic and static queries.
Persistence Units
A persistence unit defines a set of all entity classes that are managed by EntityManager instances in an application. This set of entity classes represents the data contained within a single data store.
Persistence units are defined by the
persistence.xml
configuration file. The JAR file or directory whoseMETA-INF
directory containspersistence.xml
is called the root of the persistence unit. The scope of the persistence unit is determined by the persistence unit's root.Each persistence unit must be identified with a name that is unique to the persistence unit's scope.
Persistent units can be packaged as part of a WAR or EJB JAR file, or can be packaged as a JAR file that can then be included in an WAR or EAR file.
If you package the persistent unit as a set of classes in an EJB JAR file,
persistence.xml
should be put in the EJB JAR'sMETA-INF
directory.If you package the persistence unit as a set of classes in a WAR file,
persistence.xml
should be located in the WAR file'sWEB-INF/classes/META-INF
directory.If you package the persistence unit in a JAR file that will be included in a WAR or EAR file, the JAR file should be located:
The persistence.xml File
persistence.xml
defines one or more persistence units. The following is an examplepersistence.xml
file.<persistence> <persistence-unit name="OrderManagement"> <description>This unit manages orders and customers. It does not rely on any vendor-specific features and can therefore be deployed to any persistence provider. </description> <jta-data-source>jdbc/MyOrderDB</jta-data-source> <jar-file>MyOrderApp.jar</jar-file> <class>com.widgets.Order</class> <class>com.widgets.Customer</class> </persistence-unit> </persistence>This file defines a persistence unit named
OrderManagement
, which uses a JTA-aware data sourcejdbc/MyOrderDB
. Thejar-file
andclass
elements specify managed persistence classes: entity classes, embeddable classes, and mapped superclasses. The jar-file element specifies JAR files that are visible to the packaged persistence unit that contain managed persistence classes, while the class element explicitly names managed persistence classes.The
jta-data-source
(for JTA-aware data sources) andnon-jta-data-source
(non-JTA-aware data sources) elements specify the global JNDI name of the data source to be used by the container.