This is the first part of a series of posts on JPA. In this post, I provide a concise introduction to this technology. Go through it, so that you can start developing JPA based applications following my posts at your pace.
Why JPA?
Data persistence is an essential part of almost every application. While performing data persistence using traditional JDBC, you Java developers,write complex SQL queries to store and retrieve data in the database. The JDBC API allows you to move this persistence data held by objects in the application into database tables and vice-versa by manual mapping. This task requires a lot of JDBC code to maintain and application’s interaction with the database becomes difficult to manage as complexity increases in real-world applications. JPA comes to rescue of Java developers by extending a simplified mechanism to manage data persistence in the applications.
What is JPA?
JPA (Java Persistence API) is a standard Java specification that provides an object-relational mapping (ORM) facility. It intends to form a bridge between object model in the Java application and relational model in the database so that data synchronization takes automatically between the two. JPA uses a persistent schema (i.e. persistent classes, their relationships and class instances) in the application that maps to the database schema (i.e. tables, their relationships and table rows) of the application. It creates an abstraction by hiding the complexity of the underlying database and reduces application’s burden of interaction with the database. This role of JPA in an application is shown in Figure-1.
|
Figure-1: Role of JPA |
JPA provides a persistent API, a query language and ORM metadata annotations to manage data persistence. All the classes, interfaces and annotations that make up the Java Persistence API are available in a single package named “javax.persistence”. JPA was introduced as part of Java EE 5 platform and can be used in both Java EE and Java SE applications.
JPA Providers
JPA is a usable and functional specification of Java. There are several implementations of JPA which are called JPA providers. The providers implement standard features defined in the specification and free to extend that with custom features or add proprietary functionality making them different from each other. Some of the well-known JPA implementations are: EclipseLink, Hibernate and OpenJPA.
EclipseLink JPA is the reference implementation of JPA specification. This is an open source persistence framework providing advanced support for leading databases and Java application servers. Hibernate implements JPA specifications in addition to its native API. It is an advanced and widely used persistence framework. OpenJPA is an open source JPA implementation from Apache Software Foundation.
Benefits of JPA
JPA boosts developer’s productivity and enhances software quality by offering many benefits when used in an application. These benefits can be attributed to the following aspects.
- Domain Modeling: When using JPA, it is possible to generate Java classes from existing database tables (bottom-up mapping) and database tables from existing Java classes (top-down mapping) with an appropriate tool. These Java classes represent persistent business objects in the domain. Further, business methods can be added to these classes making the domain model rich in behavior. Thus JPA facilitates better domain modeling in the application.
- Managing Persistence: JPA harnesses the best features of JDBC, JDO and other ORM frameworks. JPA simplifies the persistence programming model significantly. Entities in JPA are simple Java classes (i.e. POJO, plain old Java objects). JPA supports the large data sets, synchronizes data automatically, and handles concurrency and consistency effectively. JPA enhances query capabilities of traditional SQL making it object-oriented and more efficient through JPQL (Java Persistence Query Language).
- No Vendor Lock-in: JPA is supported by many application servers and persistent products. There are many free and open source implementations of JPA available which provide enterprise level support. JPA is independent of any product and applications can switch across the supported products as long as you use standard features of the product.
Components of JPA
In order to develop JPA based Java applications, you need to understand its major components such as Entity, EntityManager, Persistence Unit and EntityTransaction. The relationship among them is depicted the Figure-2.
|
Figure-2: Components of JPA |
Entity:
Entities form the heart of any JPA based application. An entity is a POJO class that models a persistence domain object in the application. It represents a table in a relational database. The persistence properties of an entity class represent the columns in the table. An instance of the entity class corresponds to a row in the table. Annotations are used for this object-relational mapping.
An entity has three main characteristics such as persistence, identity and transactional. The persistence characteristic deals with storing and retrieving of entity instances to and from a database. The identity characteristic is usually used to identify an entity in a database uniquely. All the CRUD operations (Create, Read, Update and Delete) for entity instances will occur within a transactional context as the real state of an entity depends whether a transaction completes or not.
Any Java class implementing serializable interface with a zero-argument constructor, getter and setter methods for its properties can be made an entity. The class is marked with @Entity annotation. By default the table name will be name of the class. We can change the default table name by setting a value to the name attribute of the annotation. A property of the class that corresponds to a table column can take @Column annotation. The name of a column, its size, whether it can accept null value or not etc., can be customized using the @Column annotation. A property that is marked with @Id annotation will be treated as a primary key for the table and is used to identify an entity instance uniquely. By default, all the properties of a class are persistent except those marked with the @Transient annotation. All these annotations are available in the javax.persistence package.
The Java class in Listing-1 forms an entity for an employee table with the following schema:
EMPLOYEE (EMPID INTEGER PK NOT NULL,
EMPNAME VARCHAR (50) NOT NULL,
DESIGNATION VARCHAR (20))
Listing-1: The Employee entity
import javax.persistence.*;
import java.io.Serializable;
@Entity (name = "EMPLOYEE") // Name of the entity
public class Employee { // This column is the primary key
@Id // default column name is the same as the property name
@Column(name = "EMPID", nullable = false)
private long empId;
@Column(name = "EMPNAME", nullable = false, length = 50)
private String empName; @Column(name = "DESIGNATION", nullable = true, length = 20)
private String designation;
public Employee() { }
- - -
// getter and setter methods go here
}
EntityManager
Entities in an application are managed by EntityManager instances. Each EntityManager instance is associated with a persistence context. A persistence context is an active collection of entity instances that are being used by the application and exist in a particular data store. In other words, a persistence context contains in-memory entity instances representing entity instances in the data store. Within the persistence context, the entity instance and their life cycle are managed.
The EntityManager has methods to create and remove persistent entity instances, find entities by their primary key, and query over entities. An EntityManager can be one of two types: container-managed or application-managed.
Container-Managed EntityManager: A container-managed EntityManager is that whose life-cycle is managed by the Java EE container. Only one instance of the EntityManager is available to the application components directly through dependency injection. The associated persistence context is automatically propagated to all application components that use the EntityManager instance.
The instance of the EntityManager is obtained using annotation:
@PersistenceContext
EntityManager em;
Application-Managed EntityManager: If the life-cycle of the EntityManager is managed by the application, several EntityManager instances are used in the application. The persistence context is not automatically propagated to application components. In this case, each EntityManager creates a new, isolated persistence context. The application explicitly creates and destroys EntityManager instances and associated persistence contexts. The createEntityManager() method of an EntityManagerFactory instance is used to create an EntityManager instance. An EntityManagerFactory instance is associated with one persistence unit. A persistence unit defines a set of entities existing in a data store. The EntityManagerFactory instance can be obtained either through dependency injection or manually using lookup method.
The following code is used to obtain EntityManagerFactory using dependency injection in Java EE environment.
@PersistenceUnit
EntityManagerFactory emf;
EntityManager em = emf.createEntityManager();
The cretateEntityManagerFactory()method of the Persistence bootstrap class is used to obtain an EntityManagerFactory in Java SE environments. It is available in a Java EE container environment as well.
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("PersistenceUnitName");
EntityManager em =
emf.createEntityManager();
PersistenceUnit
A PersistenceUnit defines a logical grouping of all entity classes managed by EntityManager instances in an application. These entity classes represent the tables in a database. One or more persistence units can be defined in a persistence.xml configuration file. The following is an example persistence.xml file:
<persistence>
<persistence-unit name="EmployeePU" transaction-type=" RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<non-jta-data-source>empData</non-jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables">
</property>
</properties>
</persistence-unit>
</persistence>
Entity operations that modify the database must be performed within an active transaction context. The transaction context can be based on either JTA transaction or non-JTA transaction. JTA transaction is usually used for container-managed EntityManager while non-JTA transaction can be used for an application-managed EntityManager which is resource-local. An EntityTransaction instance represents the transaction context and manages database transactions for a resource-local EntityManager. It has methods to demarcate a transaction boundary during entity operations. Modifications to the entity are confined to the memory until a transaction is ended. The begin() method is used to begin a transaction and either commit() or rollback() is used to end the transaction. When all the entity operations are successfully ended, commit() method is called to synchronize data with the underlying database. If the transaction is ended unsuccessful, rollback() method is called to rollback the current transaction discarding the changes made to the database if any. However, by default, the in-memory instance of the managed entity is not affected by the rollback and is not returned to its pre-modified state. An EntityManager instance invokes its getTransaction() method to create one instance of EntityTransaction.
The EntityManager uses a query language, JPQL (Java Persistence Query language) to query entities. An instance of the EntityManager may create several instances of Query in order to query on entities. An instance of Query represents a JPQL query or a native SQL query and is used to control execution of the query. The Query instance supports applying lock on the query and allows paging on query results.
In this part of the post, I introduced JPA briefly. In the next post of this series, I will discuss on how JPA manages entities and query entities using JPQL. Keep following me at this site.