The lib directory contains all the JAR files that the tutorial application depends on. In particular, this includes:

JSF and JSTL JARs (included)

JDBC driver JARs (user-supplied)

EclipseLink JAR files (user-supplied)

persistence-unit/

Contains the source files for persistent JPA entities.

classes/

This is a temporary directory where the persistence unit source files are built before packaging into the persistence unit archive.

deploy/

This directory will contain the built and packaged persistence unit persistence-unit.jar file.

src/

This directory contains the sources required for the persistence unit including the domain classes.It also contains the persistence.xml file located in the sub-directory META-INF, as per the JPA specification.

web-application/

Contains the source files that implement the services and user interface of the tutorial application that use the JPA entities.

classes/

This is a temporary directory where the sources are built before packaging into the deployable archive.

deploy/

This directory will contain the built deployable Web application, jpa-example.war. This is built using the ant target package.webapp.

This directory includes the sources for the controller layer of the application.

The org/eclipse/persistence/jpa/example/inventory/services directory contains the sources for the services interfaces that provide access to the persistence layer:

The org/eclipse/persistence/jpa/example/inventory/services/impl directory contains the classes that implement the service interfaces.The ManagedOrderBean implements the OrderService interface.The ManagedInventoryBean implements the InventoryService interface.The JPAResourceBean is a helper class that the tutorial application uses to acquire an EntityManager for the tutorial application's persistence unit.

Annotating the Entities

Annotations are a simple, expressive means of decorating Java source code with metadata that is compiled into the corresponding Java class files for interpretation at runtime by a JPA persistence provider to manage JPA behavior.

Persistent classes are decorated with JPA annotations to tell the JPA persistence provider what classes require persistence and to specify persistent class details.

In most cases, you can rely on JPA defaults. This tutorial shows the required annotations and some common optional annotations.

Annotating the Inventory Entity

This section describes how to annotate the Inventory.java file. This is a plain old Java object (POJO). It is one of the persistent entities we want to manage using EclipseLink JPA.

In Eclipse, open the <TUTORIAL_HOME>\persistence-unit\src\org\eclipse\persistence\jpa\example\inventory\model\Inventory.java source file.

Designate this class as a persistent entity using the @Entity annotation as this example shows.
@Entity in Inventory.java

@Entity
public class Inventory {
...
}

By default, the name of an entity is its class name.Also by default, the entity name is the name of the entity's database table. You can use the @Table annotation to override this default behavior (for an example, see Annotating the Order Entity).

An entity's table will contain all its persistent fields. JPA specifies that all the fields of an entity are persistent unless they are decorated with the @Transient annotation.

Designate a persistent field as the entity's primary key using the @Id annotation as this example shows.
@Id in Inventory.java

Each entity must have a primary key.The Inventory class field id is designated as the primary key. In this case, a @GeneratedValue annotation is not used because the Inventory entity gets its primary key value from its Item as the Inventory method setItem shows.

Specify the characteristics of the database table column that corresponds to the primary key field using the @Column annotation as this example shows.
@Column in Inventory.java

By default, JPA specifies that for each entity, each persistent field will correspond to a column in the entity's relational database table where the column name and type correspond to the field name and type.You can use the @Column annotation to override this default behavior.In the Inventory class, the @Column annotation is used to fine-tune the relational database column for field id as @Column in Inventory.java shows. Because the Inventory entity gets its primary key value from its Item as the Inventory method setItem shows, we must ensure that this value is never overwritten in the database. In this case, we use the @Column annotation to configure the column as not insertable or updatable. This means the JPA persistence provider will not include this column in SQL INSERT or SQL UPDATE statements. Because this column contains the foreign key to the Inventory class's Item, we use the @Column annotation attribute name to specify a name for this column that we can use when we specify the join column for the OneToOne mapping we will make to Item (see step 5 and 6).

Specify the relationship between the Inventory entity and the Item entity using the @OneToOne annotation as this example shows.
@OneToOne in Inventory.java

By default, a JPA persistence provider will automatically manage basic mappings (for most Java primitive types, wrappers of the primitive types, and enums). You can use the @Basic annotation to fine-tune basic mappings.You must specify mappings for relationships. In addition to the @OneToOne annotation, you can use the following annotations for relationship mappings:

The Inventory class field version is decorated with the @Version annotation to specify it as the optimistic locking field.By default, a JPA persistence provider assumes that the application is responsible for data consistency. We recommend that you use the @Version annotation to enable JPA persistence provider-managed optimistic locking by specifying the version field or property of an entity class that serves as its optimistic lock value.

Define a named query using the @NamedQuery annotation as this example shows.
@NamedQuery in Inventory.java

In a JPA application, you can use an EntityManager to create JPA query language queries dynamically at runtime or you can pre-define such queries using the @NamedQuery annotation and execute them by name at runtime (see Using JPA Queries). This is convenient for frequently used or complex queries.If you want to define two or more named queries, you must use the @NamedQueries annotations as is done in Order.java (see @NamedQueries in Order.java).You can also create native SQL queries (see @NamedNativeQuery and the @NamedNativeQueries).

Save and close the file.

Annotating the Item Entity

This section describes how to annotate the Item.java file. This is a plain old Java object (POJO). It is one of the persistent entities we want to manage using JPA.

In Eclipse, open the <TUTORIAL_HOME>\persistence-unit\src\org\eclipse\persistence\jpa\example\inventory\model\Item.java source file.

Designate this class as a persistent entity using the @Entity annotation as this example shows.
@Entity in Item.java

@Entity
public class Item {
...
}

Designate a persistent field as the entity's primary key using the @Id annotation as this example shows.
@Id in Item.java

The Item class property getSKU is designated as the primary key as @Id in Item.java shows. In general, you can annotate either the field (as in Inventory.java) or the property associated with a field. The @GeneratedValue annotation tells the JPA persistence provider to take responsibility for sequencing: generating and managing unique identifier values for this field.

Specify a persistent field as the optimistic locking field using the @Version annotation as this example shows.
@Version in Item.java

The Item class property setVersion is decorated with the @Version annotation to specify that corresponding field version is the optimistic locking field.

Save and close the file.

Annotating the Order Entity

This section describes how to annotate the Order.java file. This is a plain old Java object (POJO). It is one of the persistent entities we want to manage using JPA.

In Eclipse, open the <TUTORIAL_HOME>\persistence-unit\src\org\eclipse\persistence\jpa\example\inventory\model\Order.java source file.

Designate this class as a persistent entity using the @Entity annotation as this example shows.
@Entity in Order.java

@Entity
public class Order {
...
}

By default, the name of an entity is its class name and, also by default, the entity name is the name of the entity's database table.For Order entities, you cannot create a table named ORDER because that name is a reserved word in most relational databases. In this case, we use the @Table annotation to override the default table name as this example shows.
@Table in Order.java

@Entity
@Table(name="ORDER_TABLE")
public class Order {
...
}

Designate a persistent field as the entity's primary key using the @Id annotation as this example shows.
@Id in Order.java

The Order class field orderId is designated as the primary key. The @GeneratedValue annotation tells the JPA persistence provider to take responsibility for sequencing: generating and managing unique identifier values for this field.

Specify the relationship between the Order entity and the Item entity using the @OneToOne annotation as this example shows.
@OneToOne in Order.java

The Order class field version is decorated with the @Version annotation to specify it as the optimistic locking field.By default, a JPA persistence provider assumes that the application is responsible for data consistency. We recommend that you use the @Version annotation to enable JPA persistence provider-managed optimistic locking by specifying the version field or property of an entity class that serves as its optimistic lock value.

Define two named queries using the @NamedQueries annotation as this example shows.
@NamedQueries in Order.java

@Entity
@Table(name="ORDER_TABLE")
@NamedQueries({
@NamedQuery(
name="shippedOrdersForItem",
query="SELECT o FROM Order o JOIN o.item i WHERE i.sKU = :itemId and o.arrivalDate is not null"
),
@NamedQuery(
name="pendingOrdersForItem",
query="SELECT o FROM Order o WHERE o.item.sKU = :itemId and o.arrivalDate is null"
)
})
public class Order {
...
}

Each persistence unit must have a name. Only one persistence unit of a given name may exist in a given EJB-JAR, WAR, EAR, or application client JAR. You specify a persistence unit by name when you acquire an entity manager factory (see Acquire an Entity Manager Factory).

You define persistence units in the persistence.xml file.

To configure the persistence unit:

In Eclipse, open the <TUTORIAL_HOME>\persistence-unit\src\META-INF\persistence.xml file.

Edit the persistence.xml file as follows:

Confirm that the <provider> is org.eclipse.persistence.jpa.PersistenceProvider.

Replace the <!-- class list goes here --> comment with a <class> element for each of the persistent JPA entity classes:

The name of this persistence unit is default.
Its transaction-type is RESOURCE_LOCAL, meaning that entity managers for this persistence unit do not participate in JTA transactions.
It uses provider org.eclipse.persistence.jpa.PersistenceProvider.
Finally, persistence unit properties are set. You can use persistence unit properties to fine-tune the underlying JPA persistence provider and to specify the connection details for the underlying relational database that this persistence unit should be associated with.

Using JPA to Implement the Service

The main resource for managing the tutorial user interface is org.eclipse.persistence.jpa.example.inventory.ui.InventoryManagerBean. It contains a reference to the following classes that use JPA to implement the services provided by this application:

Acquire an Entity Manager Factory

Both the ManagedOrderBean and ManagedInventoryBean use an instance of helper class org.eclipse.persistence.jpa.example.inventory.services.impl.JPAResourceBean to acquire an instance of the entity manager factory for the persistence unit named default that we defined in the persistence.xml file (see Configuring the Persistence Unit). This example shows how the entity manager factory is acquired.

Once acquired, the ManagedOrderBean and ManagedInventoryBean classes use the entity manager factory to obtain an entity manager to perform all the basic persistence operations (create, read, update, and delete).

Create an Entity

This example shows how the ManagedOrderBean uses its EntityManager to create a new Order entity.

Use the EntityManager method createQuery to create a dynamic query as this example shows.
Using a Dynamic Query in ManagedInventoryBean

public class ManagedInventoryBean implements InventoryService{
...
//Returns a list of available item categories
public Collection<Category> getCategories(){
//Create an EntityManager from the Factory stored in the JPAResourceBean
EntityManager em = jpaResourceBean.getEMF().createEntityManager();
try{
//execute a JPQL query that collects summary data and stores it in a
//non-entity class Category. This query will pass the results of the
//query into the constructor of Category and return a list of Category
//objects
Collection<Category> result = em.createQuery("Select new org.eclipse.persistence.jpa.example.inventory.nonentity.Category(i.category) from Item i group by i.category").getResultList();
return result;
}finally{
em.close();
}
}
...
}

Note that this query builds and returns a Collection of Category classes that are not entity classes. It uses summary data to create this non-entity helper class.

Save and close the file.

Using Queries in the ManagedOrderBean Class

This section describes how to code named and dynamic queries in the ManagedOrderBean.java file.

In Eclipse, open the <TUTORIAL_HOME>\web-application\src\org\eclipse\persistence\jpa\example\inventory\services\impl\ManagedOrderBean.java source file.

Use the EntityManager method createNamedQuery to return a Query instance for the query named inventoryForCategory as this example shows.
Using a Named Query in ManagedOrderBean

public class ManagedOrderBean implements OrderService{
...
// Returns those orders that have a set arrival date indicating that they have shipped
public Collection<Order> getShippedOrdersForItem(long itemId){
//Create an EntityManager from the Factory stored in the JPAResourceBean
EntityManager em = jpaResourceBean.getEMF().createEntityManager();
try{
//create an instance of the NamedQuery defined in the Inventory class.
Query query = em.createNamedQuery("shippedOrdersForItem");
//setting the provided parameters on the query
query.setParameter("itemId", itemId);
//return result of query
return query.getResultList();
}finally{
em.close();
}
}
// Returns those orders that have a set arrival date indicating that they have shipped
public Collection<Order> getPendingOrdersForItem(long itemId){
EntityManager em = jpaResourceBean.getEMF().createEntityManager();
try{
Query query = em.createNamedQuery("pendingOrdersForItem");
query.setParameter("itemId", itemId);
return query.getResultList();
}finally{
em.close();
}
}
...
}

Use the EntityManager method createQuery to create a dynamic query as this example shows.
Using a Dynamic Query in ManagedOrderBean

public class ManagedInventoryBean implements InventoryService{
...
//Returns a list of available item categories
public Collection<Category> getCategories(){
//Create an EntityManager from the Factory stored in the JPAResourceBean
EntityManager em = jpaResourceBean.getEMF().createEntityManager();
try{
//execute a JPQL query that collects summary data and stores it in a
//non-entity class Category. This query will pass the results of the
//query into the constructor of Category and return a list of Category
//objects
Collection<Category> result = em.createQuery("Select new org.eclipse.persistence.jpa.example.inventory.nonentity.Category(i.category) from Item i group by i.category").getResultList();
return result;
}finally{
em.close();
}
}
...
}

As this example shows, use the appropriate EntityManager methods to transactionally find an Order by primary key and remove it.
Finding and Removing an Order in a Transaction in ManagedOrderBean

public class ManagedInventoryBean implements InventoryService{
...
// request that an order be canceled. Assume success if no exception is thrown
public void requestCancelOrder(long orderId){
//Create an EntityManager from the Factory stored in the JPAResourceBean
EntityManager em = jpaResourceBean.getEMF().createEntityManager();
try{
//changes will be made so begin a transaction
em.getTransaction().begin();
//find the order that will be deleted. This step ensures the order
//will be managed as the specification requires the object be
//managed before remove can be called.
Order order = em.find(Order.class, orderId);
//set the order to be delet4ed
em.remove(order);
//commit the transaction, this will cause the the delete SQL to be
//sent to the database.
em.getTransaction().commit();
}finally{
em.close();
}
}
// request that an order be canceled assume success if no exception is thrown
public void alterOrderQuantity(long orderId, int newQuantity){
EntityManager em = jpaResourceBean.getEMF().createEntityManager();
try{
em.getTransaction().begin();
//ensure that this order is a managed object.
Order order = em.find(Order.class, orderId);
//update the order object directly
order.setQuantity(newQuantity);
//commit the transaction to have the update sent to the database
em.getTransaction().commit();
}finally{
em.close();
}
}
// Create a new order request for a particular item;
public void createNewOrder(Order order){
EntityManager em = jpaResourceBean.getEMF().createEntityManager();
try{
em.getTransaction().begin();
//calling persist on the order object will mark the object as new
//within the persistence context.
em.persist(order);
//commit the transaction to have the object data inserted to the
//database
em.getTransaction().commit();
}finally{
em.close();
}
}
...
}

As this example shows, use EntityManager method find to retrieve an Order by primary key.
Finding an Order by Primary Key in ManagedOrderBean

Compiling and Packaging the Application

To compile and package the tutorial application, from the command line, change directories to the <TUTORIAL_HOME> directory and execute the following:

ant -f build.xml package.webapp

This creates <TUTORIAL_HOME>\web-application\deploy\jpa-example.war.

In this tutorial, we package the persistence unit in WEB-INF\lib\persistence-unit.jar within the jpa-example.war file. By confining the persistence unit to its own JAR file, you can easily re-use the persistence unit in other applications.

Copy the jpa-example.war file to the Tomcat CATALINA_HOME\webapps directory.

Start Tomcat from the command line:On Windows:

cd %CATALINA_HOME%
cd bin
startup.cmd

On UNIX:

cd $CATALINA_HOME
cd bin
startup.sh

Confirm that the application deploys successfully by looking for the log message "deployWAR INFO: Deploying web application archive jpa-example.war" on standard out or in the CATALINA_HOME/logs/catalina.out log file.

Run the Application

This section describes how to access the application after deployment:

Running the Application on Tomcat

Start a browser and enter the following URL:

http://<hostname>:8080/jpa-example/ or
http://<hostname>:8080/jpa-example/index.jsp

Where <hostname> is the name of the computer you deployed the application to.

Summary

This tutorial described a JSF Web application that manages persistence using JPA.