Skip Headers
Oracle® Containers for J2EE Enterprise JavaBeans Developer's Guide
10g Release 3 (10.1.3)
B14428-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

Accessing an EJB 3.0 Entity Using an EntityManager

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?".

Acquiring an EntityManager

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:

Using Annotations in an EJB 3.0 EJB Client

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);
    }
...
}

Using the InitialContext in an EJB Client

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 the InitialContext in a Web Client

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 the UserTransaction 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)
        {
            ...
        }
...
    }
}

Creating a New CMP Entity Instance

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 use EntityManager 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);
    }
...
}

Querying for an EJB 3.0 Entity Using the EntityManager

Using the EntityManager, you can:

For more information, see:

Finding an Entity by Primary Key with the Entity Manager

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);
    }
...
}

Creating a Named Query with the EntityManager

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-8 Creating a Named Query with the EntityManager

Query queryEmployeesByFirstName = entityManager.createNamedQuery(
    "findAllEmployeesByFirstName"
);
queryEmployeeByFirstName.setParameter("firstName", "John");
Collection employees = queryEmployessByFirstName.getResultList();

Creating a Dynamic EJB QL Query with the Entity Manager

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.

Example 29-10 Creating a Dynamic EJB QL Query with Parameters Using the EntityManager

Query queryEmployees = entityManager.createQuery(
    "SELECT OBJECT(emp) FROM Employee emp WHERE emp.firstName = :firstname"
);
queryEmployeeByFirstName.setParameter("firstName", "John");

Creating a Dynamic TopLink Expression Query with the EntityManager

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;
    }
...
}

Creating a Dynamic Native SQL Query with the EntityManager

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 support EntityManager 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.

Example 29-13 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);

Configuring Query Hints

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

fetchSize

java.lang.Integer

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.

referenceClass

java.lang.Class

Overrides the target class of the query.

cacheUsage

java.lang.Integer

Specifies how the query uses the TopLink cache. Values are as defined for the following fields of oracle.toplink.queryframework.ObjectLevelReadQuery:

  • CheckCacheByExactPrimaryKey

  • CheckCacheByPrimaryKey

  • CheckCacheOnly

  • CheckCacheThenDatabase

  • ConformResultsInUnitOfWork

For more information, see:

refresh

java.lang.Boolean

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.

lockMode

java.lang.Integer

Specifies whether or not the query uses pessimistic locking. Values are as defined for the following fields of oracle.toplink.queryframework.ObjectLevelReadQuery:

  • LOCK: issues SELECT .... FOR UPDATE.

  • LOCK_NOWAIT: issues SELECT .... FOR UPDATE NO WAIT.

  • NO_LOCK: pessimistic locking is not used.

  • DEFAULT_LOCK_MODE: fine grained locking will occur.

For more information, see the Oracle TopLink API Reference.

expression

oracle.toplink.expressions.Expression

Allows querying using the TopLink Expression API

For more information, see:

timeout

java.lang.Integer

Sets the query timeout in milliseconds.


Executing a Query

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.

Example 29-16 Executing a Query that Returns a Single Result

Object obj = query.getSingleResult();

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.

Example 29-17 Executing an Updating Query

Query queryRenameCity = entityManager.createQuery(
    "UPDATE Address add SET add.city = 'Ottawa' WHERE add.city = 'Nepean'"
);
int rowCount = queryRenameCity.executeUpdate();

Modifying a CMP Entity Instance

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").

Using an Updating Query

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").

Using the Entity's Public API

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.

Refreshing from the Database

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.

Example 29-18 Refreshing an Entity from the Database

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession
{
...
    public void undoUpdateEmployee(Integer employeeId)
    {
        Employee employee = (Employee)entityManager.find("Employee", employeeId);
        em.refresh(employee);
    }
...
}

Removing an Entity

As Example 29-19 shows, you can use EntityManager method remove to delete an entity from the database.

Example 29-19 Removing an Entity

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession
{
...
    public void removeEmployee(Integer employeeId)
    {
        Employee employee = (Employee)entityManager.find("Employee", employeeId);
        ...
        entityManager.remove(employee);
    }
...
}

Using Flush

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();
    }
...
}

Detaching and Merging a CMP Entity Bean Instance

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.

Example 29-21 Merging an Entity into the Persistence Context of an EntityManager

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession
{
...
    public void updateAddress(Address addressExample)
    {
        entityManager.merge(addressExample);
    }
...
}