http://www.developer.com/java/ent/getting-started-with-eclipselink-and-jpa-2.html

Back to article

Getting Started with EclipseLink and JPA 2


December 15, 2010

Data persistence plays a vital role in Java enterprise applications. The Java Persistence API (JPA), initially released as part of the Java EE 5 specification, was very useful for implementing data persistence when building Java EE applications. JPA 2, the latest version released as part of Java EE 6, introduces various new and interesting features.

Being a specification, JPA must be implemented by reference implementers or as products like TopLink Essentials (reference implementation for JPA 1.x), Hibernate, OpenJPA, etc. The reference implementation of JPA 2 is EclipseLink (the default implementation), which is an open source ORM solution from the Eclipse Foundation. The latest release of EclipseLink at the time of writing was EclipseLink 2.1.1, which was released in August 2010.

In our previous Developer.com articles, we explored many of the new features in JPA 2 such as new annotations, criteria queries and pessimistic locking. In this article we introduce EclipseLink and explain how to use it in JPA 2 applications for both Java SE and Java EE environments. We explain the features and provide several code snippets and snapshots for building a demo application in the Eclipse IDE. To develop the demo app, we used Eclipse 3.6 (Eclipse Helios) because it supports Java EE 6 completely, but Eclipse 3.5 (Eclipse Galileo) and NetBeans will work just as well.

Introducing EclipseLink

EclipseLink, the reference implementation of JPA 2 can be downloaded from http://www.eclipse.org/eclipselink/downloads/.

The two main JARs needed for building JPA 2 applications are:

  • eclipselink.jar
  • javax.persistence.jar

When building JPA 2 applications either in NetBeans or Eclipse, the only requirement is to add these JAR files into the project classpath. The developer need not bother with installing any other extra application to make the JPA 2 application work.

Apart from providing an implementation for the JPA 2 specification, EclipseLink also adds a set of new annotations as part of the org.eclipse.persistence.annotations package. These annotations can be used in conjunction with the JPA 2 standard annotations. A few of the newly introduced annotations in EclipseLink are listed in the table below.

Annotation

Description

@BasicMap

For storing a collection of maps that store key value pairs

@JoinFetch

For enabling joining of related objects while querying the database

@Mutable

For marking that the value of the property cannot be modified

@BasicCollection

For storing a collection of simple types in an entity

Building JPA 2 Applications Using EclipseLink in Java SE

Developing a JPA 2 application that uses EclipseLink as the persistence provider does not involve much overhead. In this section, we describe the steps for building such applications with Eclipse and the MySQL database in Java SE. We do not focus on any of the trivial concepts.

Let's begin with a simple STUDENT table structured as follows:

Student

id - int

name - String

age - int

Step 1: Create a JPA Project

The first step when building the JPA 2 application in Java SE is to create a JPA Project in Eclipse and select EclipseLink 2.0.x in the platform as shown in Figure 1. Next, open the project in the JPA perspective and add the necessary MySQL driver class.

Figure 1: Selecting the Platform in the JPA Facet
Figure 1:
Selecting the Platform in the JPA Facet

After the project is opened in the Project Explorer tab, its structure looks like Figure 2. The JPA content defines the persistence.xml configuration file.

Figure 2: JPA Project Structure
Figure 2:
JPA Project Structure

Step 2: Create the Entities by Providing All the Necessary Connection Details

The next step is to create the required entities. We chose to create entities from the table by selecting that option under JPA as shown in Figure 3. For our application, we need only one entity class: Student.

Creating Entities from a Table
Figure 3:
Creating Entities from a Table

The entity classes are the primary programming artifact required for JPA programming. Entity classes can be created by annotating the class with the @Entity, @Embeddable and @MappedSuperClass annotations defined in javax.persistence package. Here is the Student entity class:

@Entity
public class Student implements Serializable {
@Id
private Integer id;
private String name;
private Integer age;
private static final long serialVersionUID = 1L;
// public Constructor
// public Setters and Getters
}

When creating the entity classes, it is essential to provide the connection details. If the connection does not exist, a new connection should be added by clicking the icon next to the Connection drop down. After adding the connection, select the table for which the entities should be created as shown in Figure 4. After selecting the table, click the Finish button, which creates the respective entity classes.

Select Tables from the Database Connection
Figure 4:
Select Tables from the Database Connection

Step 3: Configuring EclipseLink in the Persistence.xml File

The next task is to configure the EclipseLink in the persistence.xml configuration file. For a detailed description of the properties that have changed in the persistence.xml file for JPA 2, refer to the article The JPA 2 Enhancements Every Java Developer Should Know.

For EclipseLink to be used as the provider, it is mandatory to include org.eclipse.persistence.jpa.PersistenceProvider as the value for the provider element in the persistence unit. The persistence.xml file also has to configure the data source and provide definitions for all the entity classes defined in the persistence context. Here is a sample persistence.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="JPATestProj" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.demo.infosys.Student</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa2"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="infosys"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
</properties>
</persistence-unit>
</persistence>

Step 4: Write the Client Code

After the Student entity class is created, the next step is to write the client code to insert the Student record using the javax.persistence.EntityManager instance. EntityManager instances manage the entities and are used to create, remove and find the persistent instances. EntityManager instances are obtained from the javax.persistence.EntityManagerFactory factory object. The entities are stored in the database using the javax.persistence.EntityTransaction instance. The client code is as shown below:

EntityManagerFactory emf = Persistence .createEntityManagerFactory("JPAProject");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// Create the instance of Student Entity class
Student student = new Student(147675, "Afshan", 29);
// JPA API to store the Student instance on the database.
em.persist(student);
tx.commit();
em.close();

 

Building JPA 2 Applications Using EclipseLink in Java EE

In a Java EE environment, we use GlassFish V3, a Java EE 6-compliant server that provides the environment to persist the data on to the database.

Step 1: Define a New Server

To add GlassFish V3 server, go to the Server tab in Eclipse, add a new server and then download the additional server adapters in the New Server dialogue box as shown in the Figure 5.

Adding a New Server
Figure 5:
Adding a New Server

When the adapters are displayed as shown in the Figure 6, select the GlassFish server, complete the installation and provide the Server directory.

Installing New Extension, GlassFish
Figure 6:
Installing New Extension, GlassFish

Step 2: Creating a Dynamic Web Application

After GlassFish V3 is added and configured, create a new Dynamic Web Application and select the GlassFish Server in the target runtime as shown in the Figure 7.

Creating a New Dynamic Web Project and Selecting the Target Runtime
Figure 7:
Creating a New Dynamic Web Project and Selecting the Target Runtime

Step 3: Adding JPA Facet to the Web Application

For a Java EE application, we create a connection pool on the server by configuring it in the Server console (Admin Console). For the demo application, we have created a pool named jpa2Pool. After the pool is created, add JPA in the Project Facet within the properties to enable JPA (as shown below in Figure 8).

Adding JPA in the Project Facets
Figure 8:
Adding JPA in the Project Facets

Step 4: Configuring the Application in Persistence.xml

In the persistence.xml file, select JTA as the transaction type and provide the JTA data source name in the database of the Connection tab.

Figure 9: Connection Information in Persistence.xml File
Figure 9:
Connection Information in Persistence.xml File

Here is the persistence.xml file for this application:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

<persistence-unit name="JPATestWebApp" transaction-type="JTA">
<jta-data-source>jdbc/jpa2Pool</jta-data-source>
<class>com.demo.infosys.Student</class>
</persistence-unit>

</persistence>

You can see that it is simpler in the Java EE environment; it contains only the data source name in the jta-data-source element of the persistence unit. This simplification is possible because the connection properties are already configured on the server side.

Step 5: Writing the Client Code

The client code (Servlet code) also will be different in the Java EE environment because now the EntityManager instances are managed by the server runtime and the application can look up the EntityManager and perform the required operation. We use the @PersistenceContext annotation by providing the persistence unit name, which configures the EntityManager instances for this unit.

import javax.annotation.Resource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.persistence.PersistenceContext;
import javax.servlet.annotation.WebServlet;
//Other imports
@WebServlet("/StudentServlet")
@PersistenceContext(name = "persistence/LogicalName",
unitName = "JPATestWebApp")
public class StudentServlet extends HttpServlet {
@Resource
private javax.transaction.UserTransaction utx;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try {
Context ctx = (Context) new InitialContext()
.lookup("java:comp/env");
utx.begin();
EntityManager em = (EntityManager) ctx
.lookup("persistence/LogicalName");
Student myStudent = new Student(21, "Mahalakshmi", 25);
em.persist(myStudent);
utx.commit();
} catch (Exception ex) {
ex.printStackTrace();
}
}
// Other code
}

EclipseLink Caching Ability

Data caching is essential when building an enterprise application. It becomes the most important aspect of an application when the app requires lots of database access. Caching speeds up database access and increases the performance of an application. JPA 2 supports two Levels of caches: JPA Level 1 Cache (L1) and JPA Level 2 Cache (L2). L1 cache is the persistence context and L2 cache spans across different persistence context. Find more info on JPA 2 Cache in the article JPA 2.0 Cache Vs. Hibernate Cache: Differences in Approach.

Every persistence provider has to implement the JPA 2.0 specification to provide the caching facility to cache row objects. In addition to implementing JPA 2, EclipseLink is capable of caching entities, which yields much better performance for the application. This section introduces the basics of the EclipseLink caching capability (covering every aspect of EclipseLink caching is beyond the scope of this article).

EclipseLink supports two types of cache:

  1. Session cache
  2. Unit of workcache

Session cache and unit of work cache work together to optimize the application's database access. Instances that are stored and retrieved from the database are managed and maintained by the Session cache. The Session cache stores instances that can be retrieved for future reference beyond the scope of the transaction. The first object accessed from the database is eligible to be added to the Session scope. The Unit of work cache stores instances within that transaction. When the transaction gets completed, the state of the instance gets synchronized with the database. That is when EclipseLink updates the Session cache for that object.

Objects are uniquely identified in the database using their primary key values. Within the cache, the primary key value of the persistent entity is the object identity that EclipseLink uses to uniquely identify instances. The objects in the cache are stored in the Identity Map. Caching can be enabled in EclipseLink either by using either annotations or XML files. The following code snippet shows the usage of the @Cache annotation on the Student entity class.

import org.eclipse.persistence.annotations.Cache;
import org.eclipse.persistence.annotations.CacheCoordinationType;
import org.eclipse.persistence.annotations.CacheType;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table
@Cache (type = CacheType.SOFT, shared=true, coordinationType=CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS)
public class Student {
// Some Code
}

Here is how the attributes in the code function:

  • The type attribute specifies the strategy to be used while caching the object.
    • CacheType.SOFT: This instructs the garbage collector (GC) to collect the object only when the application decides that memory might be low.
    • CacheType.WEAK: The object marked is the one that will be removed as soon as the GC is initiated.
    • CacheType.FULL: This gives full caching facility, as the objects are never flushed from the memory until they are deleted from the memory.
    • CacheType.SOFT_WEAK: This is similar to the WEAK identity map, but it uses the most frequently used sub cache.
    • CacheType.HARD_WEAK: This is similar to SOFT_WEAK but it uses the hard references in the sub cache.
  • The shared attribute is set to true, which informs EclipseLink to store the object in the L2 cache shared across the persistence context.
  • The coordinationType attribute helps EclipseLink to decide what needs to be done when the state of an instance is modified. The values that this attribute can take are:
    • INVALIDATE_CHANGED_OBJECTS: Invalidates the object in other referencing nodes. The changes made in an object do not reflect in its reference.
    • SEND_OBJECT_CHANGES: When the state is changed, it is reflected in the cache.
    • SEND_NEW_OBJECTS_WITH_CHANGES: Similar to SEND_OBJECT_CHANGES, but this is applicable only for those objects that are newly created in the transactions

Caching in JPQL

JPA provides a standard and powerful querying mechanism for querying the database. JPQL is the standard querying language used to define queries in JPA. Queries that search for instances in the shared cache are called in-memory queries. A query generally searches in the database except for those that are searching for a single instance. When a query is couched for a single instance, the instance is checked in the cache and then in the database. We can specify whether the query needs to be fired against the database or against the in-memory or against both.

The eclipselink.cache-usage hint is used to specify the interaction with the EclipseLink cache. This is a shared cache that will be shared across the persistence context. The following code snippet applies a query hint using @QueryHint. It specifies the cache usage to CheckCacheByPrimaryKey, which specifies that the cache is checked first if the query contains the primary key.

@NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e", hints={@QueryHint(name="eclipselink.cache-usage",
value=" CheckCacheByPrimaryKey")})

Conclusion

In this article, we introduced the open source ORM solution, EclipseLink. We also provided the steps required to create a JPA 2 application with EclipseLink as the provider in both Java SE and Java EE environments. Towards the end of the article, we explored the EclipseLink cache, which differentiates it from other vendors implementing JPA 2 specification.

Acknowledgements

We would like to sincerely thank Mr. Subrahmanya (SV, VP, ECOM Research Group, E&R) for his constant encouragement and Ms. Sangeetha S for providing ideas, guidance and valuable comments, and for kindly reviewing this article.

About the Authors

Mahalakshmi K. works at the E-Commerce Research Labs at Infosys Technologies Ltd. on Java EE technologies. Her core interest is in researching image processing, and she is also involved in the design and development of Java EE applications using Hibernate and JPA.

Nitin KL works at the E-Commerce Research Labs at Infosys Technologies. He is involved in design and development of Java EE applications using Hibernate, iBATIS, and JPA.

Sitemap | Contact Us