|
Oracle® Containers for J2EE Enterprise JavaBeans Developer's Guide
10g Release 3 (10.1.3) B14428-01 |
|
![]() Previous |
![]() Next |
In an EJB 3.0 application, the javax.persistence.EntityManager is the runtime access point for persisting entities to and loading entities from the database.
This section describes:
For more information, see "How Do You Query for an EJB 3.0 Entity?".
|
Note: You can download an EJB 3.0 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 EntityManager depends on your client type ("What Type of Client Do You Have?").
You can acquire an EntityManager:
In this release, you can use the @Resource annotation to inject an EntityManager in an EBJ 3.0 EJB clientsonly, as Example 29-3 shows.
Example 29-3 Using @Resource to Inject an EntityManager in a Stateless Session Bean
@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession
{
@Resource protected EntityManager entityManager;
public void createEmployee(String fName, String lName)
{
Employee employee = new Employee();
employee.setFirstName(fName);
employee.setLastName(lName);
entityManager.persist(employee);
}
...
}
Alternatively, you can acquire an EntityManager using the initial context to perform a JNDI lookup as Example 29-4 shows. In an EJB client, you use the binding:
java:comp/ejb/EntityManager
For more information, see "Configuring the Initial Context Factory".
Example 29-4 Using InitialContext to Lookup an EntityManager in a Stateless Session Bean
@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession
{
protected EntityManager entityManager;
...
public EntityManager getEntityManager()
{
if (entityManager == null)
{
try
{
entityManager = (EntityManager)(new InitialContext()).lookup(
"java:comp/ejb/EntityManager"
);
}
catch (Exception e)
{
}
}
return entityManager;
}
...
}
Using OC4J, you can acquire an EntityManager in a Web client (servlet or JSP) using the initial context to perform a JNDI lookup as Example 29-5 shows. In an EJB client, you use the binding:
java:comp/ejb/<EJB Module Name>/EntityManager
|
Note: As Example 29-5 shows, in your Web client, you must manually demarcate a transaction using theUserTransaction API because you must use the EntityManager within a transaction.
For more information, see "Configuring the Initial Context Factory". |
Example 29-5 Using InitialContext to Lookup an EntityManager in a Servlet
public class InsertServlet extends HttpServlet
{
private static final String CONTENT_TYPE = "text/html; charset=windows-1252";
...
public void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException
{
...
UserTransaction ut = null;
...
try
{
Context initCtx = new InitialContext();
ut = (UserTransaction)initCtx.lookup("java:comp/UserTransaction");
ut.begin();
Employee employee = new Employee();
employee.setEmpNo(empId);
employee.setEname(name);
employee.setSal(sal);
Context context = new InitialContext();
EntityManager entityManager = (EntityManager)context.lookup(
"java:comp/ejb/ejb30EMfromweb-ejb/EntityManager"
);
entityManager.persist(employee);
ut.commit();
this.getServletContext().getRequestDispatcher("/jsp/success.jsp").forward(
request, response
);
}
catch(Exception e)
{
...
}
...
}
}
To create a new CMP entity instance, use EntityManager method persist passing in the entity Object as Example 29-6 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-6 Creating a CMP Entity with the EntityManager
@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession
{
@Resource protected EntityManager entityManager;
...
public void createEmployee(String fName, String lName)
{
Employee employee = new Employee();
employee.setFirstName(fName);
employee.setLastName(lName);
entityManager.persist(employee);
}
...
}
Using the EntityManager, you can:
For more information, see:
As Example 29-7 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-7 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 an EJB 3.0 Named Query"), you can acquire it at runtime using EntityManager method createNamedQuery as Example 29-8 Creating a Named Query with the EntityManagershows. If the named query takes parameters, you set them using Query method setParameter.
Example 29-9 shows how to create an ad hoc EJB QL query at runtime using EntityManager method createQuery.
Example 29-9 Creating a Dynamic Query Using the EntityManager
Query queryEmployees = entityManager.createQuery( "SELECT OBJECT(employee) FROM Employee employee" );
Example 29-10 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.
As Example 29-11 shows, using the oracle.toplink.ejb.cmp3.EntityManager method createQuery(Expression expression, Class resultType), you can create a query based on a TopLink Expression.
For more information, see "Understanding TopLink Expressions" in the Oracle TopLink Developer's Guide.
Alternatively, you can use javax.persistence.EntityManager and specify the TopLink Expression as a query hint (see "Configuring Query Hints").
Example 29-11 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 the EntityManager method createNativeQuery(String sqlString, Class resultType), you can create a query based on a native SQL String that you supply as Example 29-12 shows.
Example 29-12 Creating a Dynamic Native SQL Query with the EntityManager
Query queryEmployees = entityManager.createNativeQuery( "Select * from EMP_TABLE where Salary < 50000", Employee.class );
|
Note: OC4J does not supportEntityManager method createNativeQuery(String sqlString).
|
Example 29-13 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.
A query hint is name-value pair that you can use to configure a query with a vendor-specific option that is not available in the EJB 3.0 specification.
OC4J, using the TopLink persistence manager, provides the hints shown in Table 29-3.
Example 29-14 shows how to use Query method setHint to configure a named query to always refresh the TopLink cache from the database.
Example 29-14 Configuring a Query with a Hint
Query queryEmployeesByFirstName = entityManager.createNamedQuery(
"findAllEmployeesByFirstName"
);
queryEmployeesByFirstName.setHint("refresh", new Boolean(true));
Table 29-3 Query Hints that OC4J Supports
| Hint Name | Hint Value | Description |
|---|---|---|
|
|
|
Allows the user to set the fetch size of a TopLink query in bytes. For more information, see "JDBC Fetch Size" in the Oracle TopLink Developer's Guide. |
|
|
|
Overrides the target class of the query. |
|
|
|
Specifies how the query uses the TopLink cache. Values are as defined for the following fields of
For more information, see:
|
|
|
|
Set to true if the TopLink cache should be refreshed from the database when this query executes. For more information, see "Understanding the Cache" in the Oracle TopLink Developer's Guide. |
|
|
|
Specifies whether or not the query uses pessimistic locking. Values are as defined for the following fields of
For more information, see the Oracle TopLink API Reference. |
|
|
|
Allows querying using the TopLink For more information, see:
|
|
|
|
Sets the query timeout in milliseconds. |
As Example 29-15 shows, to execute a query that returns multiple results, use Query method getResultList. This method returns a java.util.List.
Example 29-15 Executing a Query that Returns Multiple Results
Collection employees = queryEmployees.getResultList();
As Example 29-16 shows, to execute a query that returns a single result, use Query method getSingleResult. This method returns a java.lang.Object.
As Example 29-17 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 a CMP 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 EJB QL 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 an EJB 3.0 Entity Using the EntityManager").
Use the entity's public API to change its persistent state.
As Example 29-18 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-19 shows, you can use EntityManager method remove to delete an entity from the database.
As Example 29-20 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-20 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 CMP Entity Instance") or find (see "Querying for an EJB 3.0 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-21 shows, you can use EntityManager method merge to merge the state of detached entity into the current persistence context of the EntityManager.