Jump to: navigation, search

Difference between revisions of "EclipseLink/Examples/JPA/EMAPI"

(EntityManager lock())
(EntityManager refresh())
Line 186: Line 186:
 
             Employee employee = (Employee)em.find("Employee", employeeId);
 
             Employee employee = (Employee)em.find("Employee", employeeId);
 
             em.refresh(employee);
 
             em.refresh(employee);
 +
}
 +
    ...
 +
</pre></code>
 +
 +
== EntityManager clear() ==
 +
 +
Clear the persistence context, causing all managed entities to become detached. Changes made to entities that have not been flushed to the database will not be persisted.
 +
 +
<code><pre>
 +
@Stateless
 +
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
 +
    ...
 +
public void clearEmployees() {
 +
            em.clear();
 +
}
 +
    ...
 +
</pre></code>
 +
 +
== EntityManager contains() ==
 +
 +
Check if the instance belongs to the current persistence context.
 +
 +
<code><pre>
 +
@Stateless
 +
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
 +
    ...
 +
public boolean isActiveEmployee(Employee emp) {
 +
            return em.contains(employee);
 
}
 
}
 
     ...
 
     ...

Revision as of 13:26, 15 October 2007

This document demonstrates EclipseLink’s support for the JPA specification, specifically the usage of the EntityManager API

JPA greatly simplifies the development of EJBs, removing many complex development tasks. For example, creating a simple CMP entity EJB using EJB 2.1 requires a bean class and at least two interfaces, as well as a deployment descriptor. The remote (or local) and home interfaces had to extend javax.ejb.EJBObject and javax.ejb.EJBHome interfaces respectively, and the bean class had to implement the javax.ejb.EntityBean interface. However, in JPA, development is greatly simplified due to the following specifications:

  • The bean class can be a plain java class (POJO)
  • No interfaces are required for an entity bean
  • Annotations are used for O-R Mapping

Within JPA the javax.persistence.EntityManager is the application access point for persisting EntityBeans to and loading them from the database. These data operations are achieved through the API covered below.

Obtaining an EntityManager in a SessionBean

Before an EntityManager can be used it must be obtained from the container. The EntityManager can be set into your SessionBean by the Container though the @Inject annotation.

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

    @Inject protected EntityManager em;
    ...
    public EntityManager getEntityManger(){
        return this.em;
    }
    ...

Whenever the SessionBean is accessed an EnityManger will be available in the em attribute. The EntityManager can also be retrieved through a JNDI lookup.

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
    protected EntityManager em;
    ...
    public EntityManager getEntityManager() {
        if (em == null}
            try{
                em = (EntityManager)(new InitialContext()).lookup("java:comp/ejb/EntityManager");
            } catch (Exception e){};
        }
        return em;
    }
    ...

Note that the @Inject annotation is not used.

EntityManager persist()

The EntityManager persist(Object entity) API is used to mark a new instance for insert into the Database. It must only be called on new Entities. The value returned from the persist(Object entity) call is the same instance as was passed in.

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
    ...
    public void createEmployee(String fName, String lName) {
        Employee employee  = new Employee();
        employee.setFirstName(fName);
        employee.setLastName(lName);
        em.persist(employee);
    }
    ...

EntityManager merge()

To integrate a bean read in a different transaction or provided by the client into the current transaction use the meger(Object entity) API. The result will be an instance of the provided entity. The state of that entity will also be available in the returned instance.

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

EntityManager remove()

To delete a bean from the database use the remove(Object entityBean) API.

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

EntityManager find()

When a primary key query is required the find(String entityName, Object primaryKey) or find(Class entityClass, Object primaryKey) API can be used.

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

EntityManager getReference()

To retrieve an instance from the database using a primary key. This method will throw an EntityNotFoundException if the requested instance does not exist in the database.

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
    ...
    public Employee getEmployee(Integer employeeId) {
        return (Employee)em.getReference(Employee.class, employeeId);
    }
    ...

EntityManager flush()

The EntityManager flush() API is used to send updates to the database within a transaction, subsequent queries within the same transaction will return the updated data. This is useful if a particular transaction spans multiple operations or pages, similar to a "wizard".

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
    ...
    public void disemployEmployee(Integer employeeId, Date endDate) {
        Employee employee = (Employee)em.find("Employee", employeeId);
        employee.getPeriod().setEndDate(endDate);
        em.flush();
    }
    ...

EntityManager setFlushMode()

If you would like to control the way a flush() call executes, you may call setFlushMode() before hand. The flush modes are as follows:

  • COMMIT - Flushing must occur only at transaction commit.
  • AUTO - (Default) Flushing to occur at query execution.
@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
    ...
    public void disemployEmployee(Integer employeeId, Date endDate) {
        Employee employee = (Employee)em.find("Employee", employeeId);
        employee.getPeriod().setEndDate(endDate);
        em.setFlushMode(COMMIT);
        em.flush();
    }
    ...

EntityManager lock()

Use the lock(Object entity, LockModeType lockMode) when you wish to lock an entity from outside changes within a persistence context. The lock mode type can either be at the READ or WRITE level.

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

EntityManager refresh()

When the latest data is required or when changes need to be reverted in an Entity Bean the refresh(Object entity) API can be used.

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

EntityManager clear()

Clear the persistence context, causing all managed entities to become detached. Changes made to entities that have not been flushed to the database will not be persisted.

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
    ...
	public void clearEmployees() {
            em.clear();
	}
    ...

EntityManager contains()

Check if the instance belongs to the current persistence context.

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
    ...
	public boolean isActiveEmployee(Employee emp) {
            return em.contains(employee);
	}
    ...

EntityManager createQuery()

In order to perform queries based on more complex criteria queries can be created using the createQuery(string ejbqlString) or createNamedQuery(String name)

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
    ...
    public Collection findLargeProjectsWithBudgetLargerThan(double budget) {
        Collection projects = em.createNamedQuery("findWithBudgetLargerThan")
             .setParameter("amount", budget).getResultList();
        return projects;
    }

    public Project findOneProjectByQuery(Vector params) {
        Project project = (Project)em.createQuery("SELECT OBJECT(project) FROM Project project WHERE project.name = :projectName")
                .setParameter("projectName", params.firstElement()).getSingleResult();
        return project;
    }
   ...

EntityManager createQuery(Expression)

If EclipseLink's java like expressions are preferred for the query criteria, that functionality is available though the createQuery(Expression expression, Class resultType) API on the EclipseLink specific EntityManager implementation org.eclipse.persistence.jpa.JpaEntityManager.

Use the org.eclipse.persistence.jpa.JpaHelper class to retrieve the EclipseLink JpaEntityManager.

@Stateless
public class EmployeeDemoSessionEJB implements EmployeeDemoSession {
    ...
    public Collection findManyProjectsByQuery(Vector params) {
        ExpressionBuilder builder = new ExpressionBuilder();
        JpaEntityManager jpaEm = JpaHelper.getEntityManager(em);
        Query query = jpaEm.createQuery(builder.get("name").equals(builder.getParameter("projectName")), Project.class);
        query.setParameter("projectName", params.firstElement());
        Collection projects = query.getResultList();
        return projects;
    }
    ...