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

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

Line 7:

Line 9:

* Annotations are used for O-R Mapping

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

+

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.

+

+

For a complete list of the EntityManager API see, [http://www.eclipse.org/eclipselink/api/1.2/javax/persistence/EntityManager.html EntityManager].

+

+

For a list of EclipseLink's extensions to the EntityManager API see, [http://www.eclipse.org/eclipselink/api/1.2/org/eclipse/persistence/jpa/JpaEntityManager.html JpaEntityManager]

== Obtaining an EntityManager in a SessionBean ==

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

+

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 @PersistenceUnit annotation.

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

−

@Inject protected EntityManager em;

+

@PersistenceUnit

+

protected EntityManager em;

...

...

public EntityManager getEntityManger(){

public EntityManager getEntityManger(){

Line 23:

Line 30:

}

}

...

...

−

</pre></code>

+

</source>

−

Whenever the SessionBean is accessed an EnityManger will be available in the em attribute.

+

Whenever the SessionBean is accessed an EntityManger will be available in the em attribute.

The EntityManager can also be retrieved through a JNDI lookup.

The EntityManager can also be retrieved through a JNDI lookup.

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

Line 42:

Line 49:

}

}

...

...

−

</pre></code>

+

</source>

−

Note that the @Inject annotation is not used.

+

Note that the @PersistenceUnit annotation is not used.

== EntityManager persist() ==

== EntityManager persist() ==

Line 50:

Line 57:

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.

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.

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

Line 61:

Line 68:

}

}

...

...

−

</pre></code>

+

</source>

== EntityManager merge() ==

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

+

To integrate a bean read in a different transaction or provided by the client into the current transaction use the merge(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.

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

Line 75:

Line 82:

}

}

...

...

−

</pre></code>

+

</source>

== EntityManager remove() ==

== EntityManager remove() ==

Line 81:

Line 88:

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

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

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

Line 91:

Line 98:

}

}

...

...

−

</pre></code>

+

</source>

== EntityManager find() ==

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

+

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

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

...

...

−

public void removeEmployee(Integer employeeId) {

+

public Employee findEmployee(Integer employeeId) {

−

Employee employee = (Employee) em.find(Employee.class, employeeId);

+

return (Employee) em.find(Employee.class, employeeId);

−

...

+

−

em.remove(employee);

+

}

}

...

...

−

</pre></code>

+

</source>

== EntityManager getReference() ==

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

+

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

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

Line 121:

Line 126:

}

}

...

...

−

</pre></code>

+

</source>

== EntityManager flush() ==

== EntityManager flush() ==

Line 127:

Line 132:

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

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

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

Line 137:

Line 142:

}

}

...

...

−

</pre></code>

+

</source>

== EntityManager setFlushMode() ==

== EntityManager setFlushMode() ==

Line 143:

Line 148:

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

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.

+

* COMMIT - Flushing occurs only at transaction commit, or when flush() is called.

−

* AUTO - (Default) Flushing to occur at query execution.

+

* AUTO - (Default) Flushing occurs before any query execution.

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

...

...

public void disemployEmployee(Integer employeeId, Date endDate) {

public void disemployEmployee(Integer employeeId, Date endDate) {

+

em.setFlushMode(COMMIT); // Avoids find causing flush.

Employee employee = (Employee)em.find("Employee", employeeId);

Employee employee = (Employee)em.find("Employee", employeeId);

employee.getPeriod().setEndDate(endDate);

employee.getPeriod().setEndDate(endDate);

−

em.setFlushMode(COMMIT);

+

em.flush(); // Causes flush.

−

em.flush();

+

}

}

...

...

−

</pre></code>

+

</source>

== EntityManager lock() ==

== EntityManager lock() ==

Line 163:

Line 168:

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.

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.

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

Line 173:

Line 178:

}

}

...

...

−

</pre></code>

+

</source>

== EntityManager refresh() ==

== EntityManager refresh() ==

Line 179:

Line 184:

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.

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.

−

<code><pre>

+

<source lang="java">

@Stateless

@Stateless

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

Line 188:

Line 193:

}

}

...

...

−

</pre></code>

+

</source>

+

+

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

+

+

<source lang="java">

+

@Stateless

+

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

+

...

+

public void clearEmployees() {

+

em.clear();

+

}

+

...

+

</source>

+

+

== EntityManager contains() ==

+

+

Check if the instance belongs to the current persistence context.

+

+

<source lang="java">

+

@Stateless

+

public class EmployeeDemoSessionEJB implements EmployeeDemoSession {

+

...

+

public boolean isActiveEmployee(Employee emp) {

+

return em.contains(employee);

+

}

+

...

+

</source>

== EntityManager createQuery() ==

== 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)

+

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

Normally you let the JPA container manage all interaction with the datasource for your application. However, if you do require access to the datasource or connection in use by your JPA application, the following code should help you.

+

+

If you are using a JTA DataSource for your JPA persistence unit, then you can just access the JDBC Connection from the JavaEE containers DataSource. Just inject or lookup the JTA DataSource from JNDI and get a Connection from it. As long as you are within a JTA transactional context, the JDBC Connection will be the same Connection used by JPA.

+

+

If you are not using JTA, but are still using a non-JTA DataSource, then you can still access the DataSource from the container if you want a new JDBC Connection. If you want the same JDBC Connection as used by JPA, then you can access this using the JpaEntityManager interface. This will work with both a DataSource or a direct DriverManager JDBC Connection in JavaSE.

+

+

This is done differently in JPA 2.0 and JPA 1.0.

+

+

You should be in a JPA transaction to access the Connection. Otherwise, you will be responsible for releasing the connection.

Revision as of 12:47, 2 February 2012

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.

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.

EntityManager merge()

To integrate a bean read in a different transaction or provided by the client into the current transaction use the merge(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.

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

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.

Getting a JDBC Connection from an EntityManager

Normally you let the JPA container manage all interaction with the datasource for your application. However, if you do require access to the datasource or connection in use by your JPA application, the following code should help you.

If you are using a JTA DataSource for your JPA persistence unit, then you can just access the JDBC Connection from the JavaEE containers DataSource. Just inject or lookup the JTA DataSource from JNDI and get a Connection from it. As long as you are within a JTA transactional context, the JDBC Connection will be the same Connection used by JPA.

If you are not using JTA, but are still using a non-JTA DataSource, then you can still access the DataSource from the container if you want a new JDBC Connection. If you want the same JDBC Connection as used by JPA, then you can access this using the JpaEntityManager interface. This will work with both a DataSource or a direct DriverManager JDBC Connection in JavaSE.

This is done differently in JPA 2.0 and JPA 1.0.

You should be in a JPA transaction to access the Connection. Otherwise, you will be responsible for releasing the connection.