Oracle® Containers for J2EE Enterprise JavaBeans Developer's Guide 10g (10.1.3.1.0) Part Number B28221-02 |
|
|
View PDF |
In an EJB 3.0 application, the javax.persistence.EntityManager
is the run-time access point for persisting entities to and loading entities from the database.
This section describes the following:
For more information, see "How do you Query for a JPA Entity?".
Note:
You can download a JPA entity manager code example from:http://www.oracle.com/technology/tech/java/oc4j/ejb3/howtos-ejb3/howtoejb30entitymanager/doc/how-to-ejb30-entitymanager.html
.Before you can use an EntityManager
, you must acquire an EntityManager
instance. How you acquire an entity manager depends on your client type ("What Type of Client do you Have?").
When you acquire an entity manager, you specify a persistence unit. The persistence unit defines the entity manager's configuration, including details such as which factories to use, which persistent managed classes the entity manager can manage, and what object-relational mapping metadata to use. You can only acquire an entity manager for a particular persistence unit, if your client is in the persistence unit's scope. For more information, see "What is the persistence.xml File?".
You can acquire an entity manager by doing the following:
You can use the @PersistenceContext
annotation to inject an EntityManager
in an EJB 3.0 client (such as a stateful or stateless session bean, message-driven bean, or servlet). You can use @PersistenceContext
without specifying a unitName
attribute to use the OC4J default persistence unit, as Example 29-12 shows.
Example 29-12 Using @PersistenceContext With the OC4J Default Persistence Unit
@Stateless public class EmployeeDemoSessionEJB implements EmployeeDemoSession { @PersistenceContext protected EntityManager entityManager; public void createEmployee(String fName, String lName) { Employee employee = new Employee(); employee.setFirstName(fName); employee.setLastName(lName); entityManager.persist(employee); } ... }
For more information, see "Understanding OC4J Persistence Unit Defaults".
You can use the @PersistenceContext
annotation to inject an EntityManager
in an EJB 3.0 client (such as a stateful or stateless session bean, message-driven bean, or servlet). You can use @PersistenceContext
attribute unitName
to specify a persistence unit by name, as Example 29-13 shows. In this case, you must configure the persistence unit in a persistence.xml
file.
Example 29-13 Using @PersistenceContext With a Named Persistence Unit
@Stateless public class EmployeeDemoSessionEJB implements EmployeeDemoSession { @PersistenceContext(unitName="myPersistenceUnit") protected EntityManager entityManager; public void createEmployee(String fName, String lName) { Employee employee = new Employee(); employee.setFirstName(fName); employee.setLastName(lName); entityManager.persist(employee); } ... }
For more information, see the following:
Alternatively, you can use annotations to inject a persistence context and then use JNDI to look up the entity manager, as Example 29-14 shows. In this case, you must define the persistence unit in a persistence.xml
file.
Example 29-14 Using InitialContext to Lookup an EntityManager in a Stateless Session Bean
@PersistenceContext( name=Ópersistence/InventoryAppMgrÓ, unitName=InventoryManagement // defined in a persistence.xml file ) @Stateless public class InventoryManagerBean implements InventoryManager { EJBContext ejbContext; public void updateInventory(...) { ... // obtain the initial JNDI context Context initCtx = new InitialContext(); // perform JNDI lookup to obtain container-managed entity manager javax.persistence.EntityManager entityManager = (javax.persistence.EntityManager) initCtx.lookup("java:comp/env/persistence/InventoryAppMgr"); ... } }
For more information, see the following:
In this release, you can also use the @PersistenceContext
annotation to inject an EntityManager
in a Web client such as a servlet, as Example 29-15 shows. This example injects the default EntityManager
; you can also inject a named entity manager as Example 29-13 shows. For more information, see "Annotations in the Web Tier".
Example 29-15 Using @PersistenceContext to Inject an EntityManager in a Servlet
@Resource UserTransaction ut; @PersistenceContext EntityManager entityManager; ... try { ut.begin(); Employee employee = new Employee(); employee.setEmpNo(empId); employee.setEname(name); employee.setSal(sal); entityManager.persist(employee); ut.commit(); this.getServletContext().getRequestDispatcher( "/jsp/success.jsp").forward(request, response); } catch(Exception e) { ... }
To acquire an entity manager in a class that does not support annotations and injection, namely a helper class, you must do the following:
Define a persistence unit in a persistence.xml
file.
For more information, see the following:
Declare a reference to this persistence unit at the class level in each Java EE component that makes use of the helper class. The persistence unit will appear in the Java EE component's environment (java:comp/env
).
You can do this in one of the following ways:
Using the @PersistenceContext
annotation in the Java EE component that makes use of the helper class as follows:
@PersistenceContext(name="helperPC", unitName="HelperPU") @Stateless public class EmployeeDemoSessionEJB implements EmployeeDemoSession { import com.acme.Helper; ... void doSomething() { Helper.createNewEmployee(); } }
In the @PersistenceContext
annotation, you specify:
name
: the name by which you will look up the persistence context
unitName
: the name of the persistence unit you created in step 1, that defines the characteristics of the returned entity manager.
Using a persistence-context-ref
in the appropriate deployment descriptor file for the Java EE component that makes use of the helper class (see "Configuring an Environment Reference to a Persistence Context").
In the persistence-context-ref
, you specify the following:
persistence-context-ref
: the name by which you will look up the persistence context.
persistence-unit-name
: the name of the persistence unit you created in step 1, that defines the characteristics of the returned entity manager.
In the helper class, use JNDI to look up the entity manager using the persistence unit name you defined:
public class Helper { ... int createNewEmployee() { UserTransaction ut = null; ... try { Context initCtx = new InitialContext(); ut = (UserTransaction)initCtx.lookup("java:comp/UserTransaction"); ut.begin(); Employee employee = new Employee(); employee.setEmpNo(empId); // obtain the initial JNDI context Context initCtx = new InitialContext(); javax.persistence.EntityManager entityManager = (javax.persistence.EntityManager)initCtx.lookup( "java:comp/env/helperPC" ); entityManager.persist(employee); ut.commit(); } catch(Exception e) { ... } } }
Note:
In the helper class, when you use theEntityManager
, you must manually demarcate a transaction using the UserTransaction
API, because you must use the EntityManager
within a transaction.For more information, see "Configuring the Initial Context Factory".
To create a new entity instance, after acquiring an EntityManager
("Acquiring an EntityManager"), use EntityManager
method persist
passing in the entity Object
, as Example 29-16 shows. When you call this method, it marks the new instance for insert into the database. This method returns the same instance that you passed in.
You must call this method within a transaction context.
Note:
Only useEntityManager
method persist
on a new entity. If you make changes to an existing entity, they are written to the database when the current transaction commits (see also "Using Flush").Example 29-16 Creating an Entity With the EntityManager
@Stateless public class EmployeeDemoSessionEJB implements EmployeeDemoSession { @PersistenceContext protected EntityManager entityManager; ... public void createEmployee(String fName, String lName) { Employee employee = new Employee(); employee.setFirstName(fName); employee.setLastName(lName); entityManager.persist(employee); } ... }
This section describes how to use the EntityManager
to query for EJB 3.0 entities, including:
Creating a Dynamic Java Persistence Query Language Query With the Entity Manager
Creating a Dynamic TopLink Expression Query With the EntityManager
For more information, see the following:
As Example 29-17 shows, f you know the primary key, you can use EntityManager method find to retrieve the corresponding entity from the database without having to create a query.
Example 29-17 Finding an Entity by Primary Key Using the EntityManager
@Stateless public class EmployeeDemoSessionEJB implements EmployeeDemoSession { ... public void removeEmployee(Integer employeeId) { Employee employee = (Employee)entityManager.find("Employee", employeeId); ... entityManager.remove(employee); } ... }
After you implement a named query (see "Implementing a JPA Named Query"), you can acquire it at run time using EntityManager
method createNamedQuery
, as Example 29-18 Creating a Named Query with the EntityManager shows. If the named query takes parameters, you set them using Query
method setParameter
.
Example 29-18 Creating a Named Query with the EntityManager
Query queryEmployeesByFirstName = entityManager.createNamedQuery( "findAllEmployeesByFirstName" ); queryEmployeeByFirstName.setParameter("firstName", "John"); Collection employees = queryEmployessByFirstName.getResultList();
Optionally, you can configure your query with query hints to use JPA persistence provider vendor extensions (see "Configuring TopLink Query Hints in a JPA Query").
Example 29-19 shows how to create an ad hoc EJB QL query at run time using EntityManager
method createQuery
.
Example 29-19 Creating a Dynamic Query Using the EntityManager
Query queryEmployees = entityManager.createQuery( "SELECT OBJECT(employee) FROM Employee employee" );
Example 29-20 shows how to create an ad hoc query that takes a parameter named firstname
using EntityManager
method createQuery
. You set the parameter using Query
method setParameter
.
Example 29-20 Creating a Dynamic Java Persistence Query Language Query with Parameters Using the EntityManager
Query queryEmployees = entityManager.createQuery( "SELECT OBJECT(emp) FROM Employee emp WHERE emp.firstName = :firstname" ); queryEmployeeByFirstName.setParameter("firstName", "John");
Optionally, you can configure your query with query hints to use JPA persistence provider vendor extensions (see "Configuring TopLink Query Hints in a JPA Query").
As Example 29-21 shows, using the oracle.toplink.ejb.cmp3.EntityManager
method createQuery(Expression expression, Class resultType)
, you can create a query based on a TopLink Expression
.
Optionally, you can configure your query with query hints to use JPA persistence provider vendor extensions (see "Configuring TopLink Query Hints in a JPA Query").
For more information, see "Understanding TopLink Expressions" in the Oracle TopLink Developer's Guide.
Example 29-21 Creating a Dynamic TopLink Expression Query Using the Entity Manager
@Stateless public class EmployeeDemoSessionEJB implements EmployeeDemoSession { ... public Collection findManyProjectsByQuery(Vector params) { ExpressionBuilder builder = new ExpressionBuilder(); Query query = ((oracle.toplink.ejb.cmp3.EntityManager)em).createQuery( builder.get("name").equals(builder.getParameter("projectName")), Project.class); query.setParameter("projectName", params.firstElement()); Collection projects = query.getResultList(); return projects; } ... }
Using EntityManager
methods createNativeQuery(String sqlString)
or createNativeQuery(String sqlString, Class resultType)
, you can create a query based on a native SQL string that you supply, as Example 29-22 shows.
Example 29-22 Creating a Dynamic Native SQL Query with the EntityManager
Query queryEmployees = entityManager.createNativeQuery( "Select * from EMP_TABLE where Salary < 50000", Employee.class );
Example 29-23 shows how to create an ad hoc native SQL query that takes a parameter named salary
using EntityManager
method createNativeQuer(
String sqlString, Class resultClass)
. You set the parameter using Query
method setParameter
.
Example 29-23 Creating a Dynamic Native SQL Query with Parameters Using the EntityManager
Query queryEmployees = entityManager.createNativeQuery( "Select * from EMP_TABLE where Salary < #salary", Employee.class ); queryEmployeeByFirstName.setParameter("salary", 50000);
Optionally, you can configure your query with query hints to use JPA persistence provider vendor extensions (see "Configuring TopLink Query Hints in a JPA Query").
As Example 29-24 shows, to execute a query that returns multiple results, use Query
method getResultList
. This method returns a java.util.List
.
Example 29-24 Executing a Query that Returns Multiple Results
Collection employees = queryEmployees.getResultList();
As Example 29-25 shows, to execute a query that returns a single result, use Query
method getSingleResult
. This method returns a java.lang.Object
.
As Example 29-26 shows, to execute a query that updates (modifies or deletes) entities, use Query
method executeUpdate
. This method returns the number of rows affected (updated or deleted) as an int
.
You can modify an entity instance in one the following ways:
You must perform these operations within a transaction context. When the current transaction commits, your updates will be committed to the database.
You can also send updates to the database within a transaction before commit (see "Using Flush").
Create an updating query (see "Creating a Named Query With the EntityManager" or "Creating a Dynamic Java Persistence Query Language Query With the Entity Manager") and execute the query using the EntityManager
(see "Executing a Query").
Use the EntityManager to find or otherwise query for the entity (see "Querying for a JPA Entity Using the EntityManager").
Use the entity's public API to change its persistent state.
As Example 29-27 shows, you can overwrite the current state of an entity instance with the currently committed state from the database using the EntityManager
method refresh.
As Example 29-28 shows, you can use EntityManager
method remove
to delete an entity from the database.
As Example 29-29 shows, you can use EntityManager
method flush
to send updates to the database within a transaction before the transaction is committed. Subsequent queries within the same transaction will return the updated data. This is useful if a particular transaction spans multiple operations.
Example 29-29 Sending Updates to the Database Within a Transaction
@Stateless public class EmployeeDemoSessionEJB implements EmployeeDemoSession { ... public void terminateEmployee(Integer employeeId, Date endDate) { Employee employee = (Employee) entityManager.find("Employee", employeeId); employee.getPeriod().setEndDate(endDate); entityManager.flush(); } ... }
An EntityManager
is said to have a persistence context. When you create (see "Creating a New Entity Instance") or find (see "Querying for a JPA Entity Using the EntityManager") an entity using an EntityManager
instance, the entity is said to be part of the persistence context of that EntityManager
.
While an entity is part of the persistence context of an EntityManager
, it is said to be a persistent entity.
When an entity is no longer part of this persistence context, it is said to be a detached entity.
An entity is detached from the persistence context when the persistence context ends or when an entity is serialized (for example, to a separate application tier).
As Example 29-30 shows, you can use EntityManager
method merge
to merge the state of detached entity into the current persistence context of the EntityManager
.
Example 29-30 Merging an Entity into the Persistence Context of an EntityManager
@Stateless public class EmployeeDemoSessionEJB implements EmployeeDemoSession { ... public void updateAddress(Address addressExample) { entityManager.merge(addressExample); } ... }
For more information about persistence context, see the following: