Manage relational data with the Java Persistence API

The Java Persistence API (JPA) is a Java framework that allows developers to manage relational data in J2SE and J2EE applications. Peter Mikhalenko explains what persistence is, describes how it works in the JPA, and details the simplifications achieved in the persistence specifications in the last few years.

The Java Persistence API (JPA) is a Java framework that allows developers to manage relational data in J2SE and J2EE applications. The JPA is defined as part of the EJB 3.0 specification (which is part of the Java EE 5 platform). However, you do not need an EJB container or a Java EE application server to run applications that use persistence.

Future versions of the JPA will be defined in a separate Java Specification Request and specification rather than in the EJB JSR/specification. As part of EJB 3.0, the JPA is required to be supported by any Java EE 5 implementation; it can be used in a stand-alone Java SE.

Many enterprise Java developers have been using lightweight persistent objects provided by open-source frameworks or Data Access Objects (DAOs) instead of entity beans. Entity beans and enterprise beans are considered too heavyweight and complicated; also, they could only be used in Java EE application servers. Many features of third-party persistence frameworks are incorporated into the JPA, and projects like Hibernate are now implementations of the JPA.

To truly understand how the JPA can help make EJB developers' lives easier, it's important to understand the concept from the ground up. The best place to start is with an explanation of what persistence is in this context and describe how it works in the JPA; then I'll detail the simplifications achieved in the persistence specifications in the last few years.

How persistence works in the JPA

Persistent data is information that can outlive the program that creates it. The majority of complex programs use persistent data. For instance, GUI applications need to store user preferences across program invocations; Web applications track user movements and orders over long periods of time, etc.

Lightweight persistence is the storage and retrieval of persistent data with little or no work from the developer. For example, Java serialization is a form of lightweight persistence because you can persist Java objects directly to a file with very little effort. Serialization's capabilities as a lightweight persistence mechanism pale in comparison to those provided by EJB.

The Java Persistence in the JPA consists of the API (which is defined in the javax.persistence package), the Java Persistence Query Language, and object/relational metadata.

A persistence entity is a lightweight Java class that typically represents a table in a relational database. Entity instances correspond to individual rows in the table. Entities usually have relationships with other entities, and these relationships are expressed through object/relational metadata. There are two ways that object/relational metadata can be specified: directly in the entity class file by using annotations or in a separate XML descriptor file distributed with the application.

The persistence metadata is specified using Java annotations, XML mapping files, or a combination of both. In case both are used, the XML information overwrites the annotations in the Java code. This persistence metadata defines the mapping to the database and the relationship between the objects. The Java compiler will use the metadata information (from the annotations or the XML file) to perform the correct database operations.

The JPA requires that you identify the classes that you will store in a database. The JPA uses the term Entity to define classes/interfaces that it will map to a relational database.

Other persistence specifications

There are many specifications related to persistence in Java. The following list summarizes each specification:

Comparing persistence solutions with the JPA

If you need to store and retrieve persistent data, the available options include: serialization, JDBC, JDO, proprietary object-relational mapping (ORM) tools, object databases (ODBs), and EJB 2 entity beans. Unfortunately, each of these persistence solutions has severe limitations, which the JPA attempts to overcome.

Serialization is Java's built-in mechanism for transforming an object graph into a series of bytes. It is very easy to use, but is also very limited.

JDBCovercomes most of the shortcomings of serialization. For instance, JDBC can handle large amounts of data; it has mechanisms to ensure data integrity; it supports concurrent access to information; and it has a sophisticated query language in SQL. However, JDBC has a relational paradigm, which means that the data is represented by rows and not by objects.

The JDO specification uses an API that is strikingly similar to the JPA.

There are many proprietary software products that can perform the mapping between objects and relational database tables for you. These ORM frameworks allow you to focus on the object model rather than concern yourself with the mismatch between the object-oriented and relational paradigms. The problem is that each of these products has its own set of APIs.

Rather than map objects to relational databases, some software companies have developed a database form designed specifically to store objects. These ODBs are often much easier to use than ORM software. Fewer data analysis tools are available for such solutions, and many companies have a fear for switching to the ODBs because the relational paradigm is tested and reliable, which cannot be said about object-based systems.

EJB 2.x entities were the components that represent persistent information in a datastore. EJB 2.x were difficult to code and required heavyweight and expensive application servers to run.

The JPA combines the best features from each of these persistence solutions. Creating entities under the JPA is as simple as creating serializable classes. The JPA supports the large data sets, data consistency, concurrent use, and query capabilities of JDBC. Like ORM software and ODBs, the JPA allows the use of advanced object-oriented concepts such as inheritance. The JPA avoids vendor lock-in by relying on a strict specification like JDO and EJB 2.x entities; it focuses on relational databases; and (similar to JDO) it is extremely easy to use.

Conclusion

The JPA provides a persistence model for Java objects or Plain Old Java Objects (POJOs) using ORM. While the JPA was developed by the EJB 3.0 expert group and initially became a part of EJB 3.0, you can now use it in stand-alone applications and even in a J2SE environment.

It is beyond the scope of this article to outline the details of which Java classes you should use in the JPA. For a detailed description of how to use the JPA, check out these additional resources: