Skip Headers
Oracle® Containers for J2EE Enterprise JavaBeans Developer's Guide
10g (10.1.3.1.0)

Part Number B28221-02
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

Accessing a JPA Entity Using an EntityManager

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

Acquiring an EntityManager

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:

Acquiring the OC4J Default Entity Manager

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

Acquiring a Named Entity Manager

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:

Acquiring an Entity Manager Using JNDI

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:

Acquiring an Entity Manager in a Web Client

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

Acquiring an Entity Manager in a Helper Class

To acquire an entity manager in a class that does not support annotations and injection, namely a helper class, you must do the following:

  1. Define a persistence unit in a persistence.xml file.

    For more information, see the following:

  2. 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:

    1. 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.

    2. 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.

  3. 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 the EntityManager, 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".

Creating a New Entity Instance

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

Querying for a JPA Entity Using the EntityManager

This section describes how to use the EntityManager to query for EJB 3.0 entities, including:

For more information, see the following:

Finding an Entity by Primary Key With the Entity Manager

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

Creating a Named Query With the EntityManager

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

Creating a Dynamic Java Persistence Query Language Query With the Entity Manager

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

Creating a Dynamic TopLink Expression Query With the EntityManager

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

Creating a Dynamic Native SQL Query With the EntityManager

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

Executing a 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.

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

Object obj = query.getSingleResult();

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.

Example 29-26 Executing an Updating Query

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

Modifying an Entity Instance

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

Using an Updating Query

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

Using the Entity's Public API

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.

Refreshing From the Database

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.

Example 29-27 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-28 shows, you can use EntityManager method remove to delete an entity from the database.

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

Detaching and Merging an Entity Bean Instance

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: