Java Persistence API (JPA) – Complete Guide with Example

Overview

Developers of an object oriented language want to work with objects not the relational data. When we want to store our objects or data in a database, we need to write database specific queries in our java code using JDBC. Now with this approach, there are few problems. First, we need to explicitly convert database queries into java objects and database result set into java objects. Second, we need to manually handle all database transactions. To all these problems, there is one solution – Java Persistence API.

Java Persistence API aka JPA is a specification that provides functionalities of ORM in Java. ORM stands for Object Relational Mapping. It basically an approach to map Java objects to Database tables and vice versa.

JPA allows the java developer to work directly with java objects rather than writing SQL statements.

In order to map the java objects to database tables, we need to provide persistence metadata. It can be written using XML configuration or we can also use annotations. If we use xml configuration and annotation both then annotations will be overwritten with xml configuration.

JPA solves not one but many problems, some of them are mentioned below:

  1. Java developer need not to know how to write SQL statements. They do not necessarily have the knowledge of relational database to store their objects in database.
  2. Changing the database in future would not make a lot of code efforts as we write query using query language provided by JPA.

One thing to note here is JPA is just a specification and a lot of implementations are available for it. EclipseLink and Hibernate is few of the popular implementations of JPA.

EclipseLink is sort of reference implementation of JPA.

To work with JPA, we need to learn some key concepts associated with it. Let’s understand each of them followed by a working example.

Installation and Configuration for JPA

JPA is just a specification and in order to make it work, we need to provide the implementation for JPA. To save some time, there are so many implementations for JPA already exists so let’s just use one of them.

Now this tutorial is about Java Persistence API so we will use EclipseLink for this tutorial as it’s a sample implementation for the JPA.

In addition, we will use h2 database to make things more easy to understand.

Let’s create a maven project and add following dependencies:

<!-- JPA with EclipseLink -->
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>3.0.0</version>
    </dependency>

    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>javax.persistence</artifactId>
        <version>2.2.1</version>
    </dependency>

<!-- H2 Database -->

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.4.200</version>
    </dependency>

Entity

Entity in JPA is a class whose fields will be persisted in a database. Entities in JPA are simple POJO classes with some annotations. These classes are annotated with @Entity. @Entity annotation tells JPA to persist this class in database. Each entity will correspond to one database table. Each created object of the Entity class will correspond to one row of the table.

As each entity represents a table in the database. we can declare the name for the database table using @Table annotation.

Now let’s create an entity Student to hold and persist Student(s) states:

@Entity
@Table(name="student")
public class Student {
}

If we do not provide @Table annotation then it automatically picks the class name as the table name.

Let’s create some fields that denote the students state and create getters and setters method for each state:

@Entity
@Table(name="student")
public class Student {
	
	private int rollNumber;
	private String fullName;
	private String department;
	
	
	//Getters and Setters	
}

You must follow naming convention when creating getters and setters to let JPA know the corresponding getter and setter for the field.

Each field/state of the entity/class will correspond to one column in the database table. Now let’s define column name for each column.

@Entity
	@Table(name="student")
	public class Student {
		
		@Column(name="roll_number")
		private int rollNumber;
		
		@Column(name="full_name")
		private String fullName;
		
		@Column(name="department")
		private String department;	
	}

Now we need to define one column that will act as the primary key for the student table. The column annotated with @Id will become the primary key for the table. JPA provides mechanism to auto generate the value for the primary column. We can use @GeneratedValue with GenerationType.AUTO as the parameter. Let’s define it:

@Entity
	@Table(name="student")
	public class Student {
		
		@Id
		@GeneratedValue(strategy = GenerationType.AUTO)
		private long id;
		
		@Column(name="roll_number")
		private int rollNumber;
		
		@Column(name="full_name")
		private String fullName;
		
		@Column(name="department")
		private String department;
}

There are some rules associated when we are creating an entity:

  1. The entity class must be denoted using @Entity.
  2. It must have one primary key.
  3. It cannot be declared as final.
  4. It must have a default constructor.

Suppose, we do not want any field to be saved in the database then that field should be denoted with @Transient annotation.

Entity Relationships

In the above section, we created a Student entity. OK, that’s easy. But you may ask what if a Student has relation with other Entity as well. How to manage entity relationship? What if a Student entity has an Address entity.

There are simple annotations provided by JPA to handle and manage the entity relationship. Let’s look at them:

1) One-to-One: When one entity contains a reference of another entity then this is called a one-to-one entity relationship. One entity can only contain single instance of the referenced entity. The referenced entity is annotated with @OnetoOne annotation.

2) One-to-Many: One entity can contain a collection of references of another entity. This relationship is called one-to-many entity relationship. In this case, the entity contains multiple instances of the referenced entity. For this @OnetoMany annotation is used.

3) Many-to-One: When multiple instances of an entity are related to one instance of another entity, Many-to-One entity relationship is established. @ManyToOne annotation is used in this context.

4) Many-to-Many: When multiple instances of an entity contains references of multiple instances of another entity then Many-to-Many relationship is established. This is annotated with @ManyToMany.

Entity Manager

Entity Manager is the utility that is responsible for all the operations from and to the database. It handles and manages several operations like finding the objects to persist, persisting the objects and removing the objects.

All entities are managed by the entity manager of JPA.

The entity manager is automatically available in JavaEE application. For other types of application, we need to manage it manually. It is available in javax.persistence package.

EntityManagerFactory and Persistence Unit

In order to persist the entity, we will define our persistence unit for the application. We can define it in the persistence.xml file under the META-INF folder.

The entities are managed (created, updated, and deleted) via EntityManager which is created by the EntityManagerFactory which is configured using our persistence unit aka persistence.xml file.

The persistence.xml file contains the database configuration details such as driver, user details etc.

This is how our persistence.xml file is looking for the Student application example that we are working on. This MUST BE stored in the META-INF folder inside resources folder of your project.

<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"
  version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
  
  <persistence-unit name="student-persistence" transaction-type="RESOURCE_LOCAL">
    <class>com.app.Studentt</class>
    <properties>
      <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
      <property name="javax.persistence.jdbc.url"    value="jdbc:h2:mem:test" />
      <property name="javax.persistence.jdbc.user" value="admin" />
      <property name="javax.persistence.jdbc.password" value="admin" />
    </properties>
  </persistence-unit>
</persistence>

Notice that we are using h2 database for simplicity. We have also provided a name to this persistence.xml file inside the name attribute of persistence-unit tag. It will later be used when we are creating instance for the EntityManagerFactory.

Persistence of Entity

Let us know some steps that involves in persisting an entity in JPA.

1. Get the EntityManager

EntityManager is provided by the EntityManagerFactory. First, we will create the object of EntityManagerFactory and then we will create our entity manager.

EntityManagerFactory managerFactory =Persistence.createEntityManagerFactory("student-persistence");  

EntityManagerFactory is configured using the persistence unit that’s why we have provided the name of our persistence unit in the createEntityManagerFactory method.

EntityManager manager =managerFactory.createEntityManager();  

Now we are using the instance of EntityManagerFactory to create the EntityManager instance.

2. Initializing the EntityManager / Starting the transaction

manager.getTransaction().begin();

This will get the transaction from the EntityManager instance and starts it by calling the begin() method.

3. Persisting the entity

Now we will persist our Student entity in the database. Let’s create and instance of Student and persist it using JPA EntityManager.

Student student = new Student();
student.setDepartment("CS");
student.setFullName("CHANDLER BING");
student.setRollNumber(123);
		
manager.persist(student);

4. Closing the transaction

Last step is to close the started transaction.

manager.getTransaction().commit();

This is how our final code looks like in our App.java:

package com.app;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class App {
	public static void main(String[] args) {
		EntityManagerFactory managerFactory = Persistence.createEntityManagerFactory("student-persistence");

		EntityManager manager = managerFactory.createEntityManager();

		try {

			manager.getTransaction().begin();

			Student student = new Student();
			student.setDepartment("CS");
			student.setFullName("CHANDLER BING");
			student.setRollNumber(123);

			manager.persist(student);

			manager.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			managerFactory.close();
			manager.close();
		}
	}

}

JPQL (Java Persistence Query Language)

JPQL is a query language specifically designed for Java Persistence API. It is an object oriented query language. We use this language to perform database operations on our entities. No matter what database we are using, JPQL remains same as it works on entities not database tables.

JPA transforms the JPQL to database specific query language to actually perform the database operations.

Conclusion

This tutorial helped you in understanding the ORM and JPA as its core. This API helps java developers to work on objects rather than relational data. Developers need not to know database specific syntax to store their objects into database. It also avoids the manual operation of converting objects into relational data and vice versa.

I hope you find this tutorial helpful. Thanks.

Newsletter Updates

Enter your name and email address below to subscribe to our newsletter

Leave a Reply