GlassFish
Project - Java Persistence Example
New
to GlassFish | Community
Guidelines | Downloads
| FAQ
| How-Tos
Overview
This is a very simple example that uses only 2 entities - a Customer
and an Order, with OneToMany relationships between them. The Customer
and the Order classes are Plain Old Java Classes (POJOs). These
classes, as well as the code that manipulates POJO instances, can be
used without any changes in Java SE or Java EE environment.
Accessing
an EntityManagerFactory and an EntityManager depends on the environment
and is described in more details below.
We will create
a customer and two related orders, find the customer, and navigate from
the customer to its orders, and then merge and remove all the objects.
All these
operation will be performed using Java Persistence API and require JDK 5.0.
Click here to get
the ZIP file with the complete Java SE example as a netbeans project. This example works with Java DB or with Oracle.
Click here to get the ZIP file with the complete Java SE example. This example works with Oracle.
Click here to get
the ZIP file with the complete Java EE example.
Refer to Java
Persistence API document of JSR-220:
Enterprise
JavaBeansTM
3.0 Specification for further details on annotations and APIs.
Check example sources for the
necessary import statements.
Mapping to Existing
Tables
In the first example we will use only two tables:
ORDER_TABLE
|
ORDER_ID
|
SHIPPING_ADDRESS
|
CUSTOMER_ID
|
CUSTOMER_ID column in the ORDER_TABLE is the Foreign Key (FK) to the ID
column from the CUSTOMER table. The files
sql/tables_oracle.sql and sql/tables_derby.sql
in the example contains DDL to create both tables for Oracle and Apache Derby.
POJO Classes
Now let's look at the corresponding persistence classes. Both entities
in this example use property based persistence. There is no access
annotation element on the entity, so it defaults to
access=PROPERTY. This is
the reason why @Column annotation is specified for the get methods and
not for the fields. The classes that are used as an argument or a
return type between a
remote client and a container must implement
java.io.Serializable
interface.
The POJO classes in the examples belong to an
entity package.
Customer
The Customer
entity is mapped to the CUSTOMER table, and looks like this:
@Entity
public class Customer {
private int id;
private String name;
private Collection<Order>
orders;
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name)
{
this.name
= name;
}
@OneToMany(cascade=ALL, mappedBy="customer")
public Collection<Order> getOrders() {
return orders;
}
public void setOrders(Collection<Order>
newValue) {
this.orders = newValue;
}
}
Note that there are no @Table and @Column annotations. This is possible
because the persistence provider will use the default rules to
calculate those values for you. See chapter 9 of the
Java
Persistence API Specification for detailed rules of the mapping
annotations.
Order
The Order entity
is mapped to the ORDER_TABLE table. It requires both @Table and @Column
mapping annotations because table and column names do not match class
and properties names exactly. @Column annotations are specified for the
corresponding get methods:
@Entity
@Table(name="ORDER_TABLE")
public class Order {
private int id;
private String address;
private Customer customer;
@Id
@Column(name="ORDER_ID")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="SHIPPING_ADDRESS")
public String getAddress()
{
return address;
}
public void setAddress(String
address) {
this.address
= address;
}
@ManyToOne()
@JoinColumn(name="CUSTOMER_ID")
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer
customer) {
this.customer
= customer;
}
}
Note that Customer and Order have bidirectional relationships between
the entities.
Persisting POJO Entities
Now, let's create new instances, set up the relationships and persist
all of them together using the CASCADE option that we set on the
Customer entity. This code must be executed in a context of an active
transaction.
// Create new customer
Customer customer0 = new Customer();
customer0.setId(1);
customer0.setName("Joe Smith");
// Persist the customer
em.persist(customer0);
// Create 2 orders
Order order1 = new Order();
order1.setId(100);
order1.setAddress("123 Main St. Anytown, USA");
Order order2 = new Order();
order2.setId(200);
order2.setAddress("567 1st St. Random City, USA");
// Associate orders with the customer.
Note that the association must be set on both sides of the
relationship: on the customer side for the orders to be persisted when
transaction commits, and on the order side because it is the owning
side:
customer0.getOrders().add(order1);
order1.setCustomer(customer0);
customer0.getOrders().add(order2);
order2.setCustomer(customer0);
When this transaction commits, all three entities will be
persisted in the database.
Query and
Navigation
We'll use a new EntityManager to do the query, but will execute the
query without an active transaction:
// Create new EntityManager
em = emf.createEntityManager();
Query q = em.createQuery("select c from Customer c
where c.name = :name");
q.setParameter("name", "Joe Smith");
Our query is supposed to return a single customer, so we will
use the Query method
getSingleResult()
to execute the query. This method would throw an exception if there is
no or more than one matching customers.
Customer c = (Customer)q.getSingleResult();
Now let's verify that the orders were also created by navigating from
the Customer.
You can print the orders, but we'll just check the size:
Collection<Order> orders =
c.getOrders();
if (orders == null || orders.size() != 2) {
throw new
RuntimeException("Unexpected number of orders: "
+ ((orders == null)? "null" : "" + orders.size()));
}
Merge and Removal
of Persistent
Instances
To remove an instance, it must be managed by this EntityManager. The
code below uses a customer '
c'
that had been detached from its persistence context. Removal of the
Customer also removes related orders because of the CASCADE option set
on the corresponding relationship. This code must be executed in a
context of an active transaction.
// Merge the customer to the new persistence
context
Customer c0 = em.merge(c);
Note that
merge() is not a
void operation. It returns back a managed copy of the argument (and its
related objects). Only this copy can be used for EntityManager
operations.
// Delete all records
em.remove(c0);
Putting It All Together
Using in Java SE
First, we need to create an EntityManagerFactory that we will use in
the
example. An EntityManagerFactory is created once
for each PersistentUnit. Persistent unit in this example is called
"pu1".
// Create EntityManagerFactory for persistent unit
named "pu1"
// to be used in this
test
emf = Persistence.createEntityManagerFactory("pu1");
For each business method in the example, a new EntityManager is created:
// Create new EntityManager
em = emf.createEntityManager();
If a transaction required, it is started:
// Begin transaction
em.getTransaction().begin();
And then the business logic is executed in a separate business
method:
// Business logic
mybusinessmethod(...);
If transaction has been started it must be committed:
// Commit the transaction
em.getTransaction().commit();
And EntityManager should always be closed if it won't be used
again:
// Close this EntityManager
em.close();
Java SE client code in this
example
is located in the
class
client.Client.
To run the test, you need to create
META-INF/persistence.xml
file in
the classpath. Copy META-INF/persistence.xml.template file from the
classes
directory in the example to META-INF/persistence.xml and populate the
values of the
corresponding properties with the database settings that you are using.
Note that persistence-unit name is set to "pu1" and all entity classes
are explicitly listed.
Add your database driver and classes directory
from the unzipped example to the classpath, load the tables into the
database, then run:
java
-javaagent:${glassfish.home}/lib/toplink-essentials-agent.jar
client.Client
Using the Java SE Example in Netbeans
Configuring the JDBC driver
To configure the JDBC driver to be used when running the project, right-click on the project, select properties. Click on the libraries and then click on the 'Add JAR/Folder' button to add the jars for the JDBC driver being used. In the example below, the Java DB/Derby JDBC Client Driver is added.

Creating the tables
Scripts are provided to create the tables needed for the example for either Java DB/Derby or Oracle.
Note:If you are using Oracle, go to the runtime tab, click databases and then right click drivers to add the Oracle driver so that it can be used with the SQL Editor.
- Create a connection to the database
- expand the drivers folder and right click on the Oracle or Java DB/Derby driver and create a connection to the database. For Java DB/Derby you can enter: jdbc:derby://localhost:1527/testDB;create=true and enter APP for the username and password.
- If you are using Java DB/Derby and the server is not started, Select Tools->Java DB Database ->Start Java DB server
- Open the appropriate sql script by typing Ctrl-O or selecting 'Open File' from the file menu. The SQL scripts are in the sql directory of the project.
- Select the connection to use (for Java DB/Derby you can use jdbc:derby://localhost:1527/testDB;create=true [APP on APP] .
- Click the Run SQL icon
on the right of the Connection drop-down box. This will open the Connect dialog. Enter the password for your connection. . Click OK to connect and run the SQL script.

Configuring the persistence unit
To configure the persistence unit for the sample, click on source packages and then click on META-INF. Double click on persistence.xml. Your configuration should look like the following if you are using Java DB/Derby:
Running the project:
To run the the sample application. Right click on the project and select 'Run Project'.
Using in Java EE
In a Java EE container, the client code will not create an
EntityManagerFactory - it is done by the container.
There are several option to get a hold of an
EntityManager:
- An EntityManagerFactory or an EntityManager can be injected by
the container or looked up in JNDI.
- An EntityManager instance can be acquired from an
EntityManagerFactory via the corresponding API call.
Transaction boundaries depend on the EntityManager type:
- A JTA EntityManager participates in the current JTA transaction
that is either controlled by the container or by a user via javax.transaction.UserTransaction
API.
- A resource-local EntityManager uses the same Java Persistence API
as in Java
SE environment to control
its transactions.
In our
example a JTA EntityManager is
injected by
the container into the Session Bean:
@PersistenceContext(unitName="pu1")
private EntityManager em;
Transaction boundaries set to container-managed defaults.
The client code from the Java SE example is now divided between a
Stateless
Session Bean
ejb.TestBean
(implements
ejb.Test remote
business interface), which contains the business logic (i.e. exactly
the same business methods as the Java SE client), and an
application client
client.AppClient
that calls the corresponding methods and prints the output:
// Persist all entities
System.out.println("Inserting Customer and Orders...
" + sb.testInsert());
// Test query and navigation
System.out.println("Verifying that all are
inserted... " + sb.verifyInsert());
// Get a detached instance
Customer c = sb.findCustomer("Joe Smith");
// Remove all entities
System.out.println("Removing all... " +
sb.testDelete(c));
// Query the results
System.out.println("Verifying that all are
removed... " + sb.verifyDelete());
In the Java EE environment META-INF/persistence.xml does
not need to list persistence classes, or the <provider> (if you
use the default persistence provider). It should specify
<jta-data-source>, if it does not use the default DataSource
provided by the container. The example specifies jdbc/__default, which
is the default for the Derby database, so that it is easy to replace
with another name. Java EE example uses
automatic
table generation feature in GlassFish by setting required
properties in the META-INF/persistence.xml.
To test the example, unzip it and deploy ex1-ee.ear file:
${glassfish.home}/bin/asadmin deploy --retrieve .
ex1-ee.ear
Then execute the
appclient
script:
${glassfish.home}/bin/appclient
-client ./ex1-eeClient.jar -mainclass client.AppClient
The Result
This is the output (after several extra log messages) that will be
printed:
Inserting Customer and Orders... OK
Verifying that all are inserted... OK
Removing all... OK
Verifying that all are removed... OK
Read the
packaging
rules and other useful information on the
Entity
Persistence page for the next steps.