JPA 

This tutorial will show you how to use JPA(Java Persistence API) Criteria Queries for selecting data from database.

The Java Persistence API (JPA) is a Java specification for accessing, persisting, and managing data between Java objects / classes and a relational database.

The Criteria API is used to define queries for entities and their persistent state by creating query-defining objects. Criteria queries are written using Java programming language APIs, are typesafe, and are portable. Such queries work regardless of the underlying data store. The major advantage of Criteria API is that errors can be detected earlier during the compile time. String-based JPQL(Java Persistence Query Language) queries and JPA criteria based queries are same in performance and efficiency.

Recommended Reading:

Spring Data JPA Specification Criteria Query Example

Hibernate Criteria API Example

Steps to create Criteria Query

1. EntityManager instance is used to create a CriteriaBuilder object.
2. CriteriaQuery instance is used to create a query object from CriteriaBuilder object. The attributes of this object will be modified with the details of the query.
3. CriteriaQuery.form method is called to set the Root of the query.
4. CriteriaQuery.select is called to set the result list type for a particular POJO class mapped to a database table.
5. TypedQuery<T> instance is used to prepare a query for execution and specifying the type of the query result.
6. getResultList method is used on the TypedQuery<T> object for executing a query to return the result list of a collection of entities.


The following example shows you how to use JPA Criteria Queries in an application.

For this tutorial we will create a standalone maven project in Eclipse. If you already have an idea on how to create a maven project in Eclipse will be great otherwise I will tell you here how to create a maven project in Eclipse.

Prerequisites

The following configurations are required in order to run the application

Eclipse Mars
JDK 1.8
Have maven installed and configured
JPA dependencies in pom.xml

Now we will see the below steps how to create a maven based spring project in Eclipse.

Step 1. Create a standalone maven project in Eclipse

Go to File -> New -> Other. On popup window under Maven select Maven Project. Then click on Next. Select the workspace location – either default or browse the location. Click on Next. Now in next window select the row as highlighted from the below list of archtypes and click on Next button.

maven-arctype-quickstart

Now enter the required fields (Group Id, Artifact Id) as shown below

Group Id : com.roytuts
Artifact Id : jpa

Step 2. Modify the pom.xml file as shown below.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>jpa</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>jpa</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
		<hibernate.version>4.3.10.Final</hibernate.version>
		<mysqlconnector.version>5.1.34</mysqlconnector.version>
	</properties>

	<dependencies>
		<!-- JPA -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		<!-- mysql java connector -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysqlconnector.version}</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Step 3. If you see JRE System Library[J2SE-1.5] then change the version by below process

Do right-click on the project and go to Build -> Configure build path, under Libraries tab click on JRE System Library[J2SE-1.5], click on Edit button and select the appropriate jdk 1.8 from the next window. Click on Finish then Ok.

Step 4. Create src/main/resources folder for putting the resource files.

Do right-click on the project and go New -> Source Folder. Give Folder name: as src/main/resources and click on Finish button.

Then create META-INF folder under src/main/resources source directory.

Step 5. Create an XML file persistence.xml under src/main/resources/META-INF.

Do right-click on META-INF in the project and go New -> file. Give File name: as persistence.xml and click on Finish button.

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
	version="2.1">
	<persistence-unit name="userPersistanceUnit"
		transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
		<class>com.roytuts.jpa.entity.UserDetails</class>
		<properties>
			<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
			<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/cdcol" />
			<property name="javax.persistence.jdbc.user" value="root" />
			<property name="javax.persistence.jdbc.password" value="" />

			<property name="dialect" value="org.hibernate.dialect.MySQLDialect" />
			<property name="hibernate.transaction.flush_before_completion"
				value="true" />
			<property name="hibernate.show_sql" value="true" />
			<property name="hibernate.format_sql" value="true" />
		</properties>
	</persistence-unit>
</persistence>

In the above XML file, we have transaction-type as RESOURCE_LOCAL. There are two types of Transaction management types supported in JPA.

RESOURCE LOCAL Transactions
JTA or GLOBAL Transactions

Resource local transactions refer to the native transactions of the JDBC Driver whereas JTA transactions refer to the transactions of the JEE server. A Resource Local transaction involves a single transactional resource, for example a JDBC Connection. Whenever you need two or more resources( for example a JMS Connection and a JDBC Connection )  within a single transaction, you use  JTA Transaction. Container Managed Entity Managers always use JTA transactions as the container takes care of transaction life cycle management and spawning the transaction across multiple transactional resources. Application Managed Entity Managers can use either Resource Local Transactions or JTA transactions.

Normally in JTA or global transaction, a third party transaction monitor enlists the different transactional resources within a transaction, prepares them for a commit and finally commits the transaction. This process of first preparing the resources for transaction(by doing a dry run) and then committing(or rolling back) is called a 2 phase commit.

Step 6. Create below entity class UserDetails under src/main/java folder

package com.roytuts.jpa.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "user_details")
public class UserDetails {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id")
	private int id;

	@Column(name = "first_name")
	private String firstName;

	@Column(name = "last_name")
	private String lastName;

	@Column(name = "email")
	private String email;

	@Column(name = "dob")
	private String dob;

	public UserDetails() {
	}

	public UserDetails(int id, String firstName, String lastName, String email, String dob) {
		this.id = id;
		this.firstName = firstName;
		this.lastName = lastName;
		this.email = email;
		this.dob = dob;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getDob() {
		return dob;
	}

	public void setDob(String dob) {
		this.dob = dob;
	}

	@Override
	public String toString() {
		return "UserDetails [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email
				+ ", dob=" + dob + "]";
	}

}

Step 7. Create below custom exception class JpaException under src/main/java folder

package com.roytuts.jpa.exception;

public class JpaException extends RuntimeException {

	private static final long serialVersionUID = 1L;

	public JpaException(String msg) {
		super(msg);
	}

	public JpaException(Throwable t) {
		super(t);
	}

	public JpaException(String msg, Throwable t) {
		super(msg, t);
	}

}

Step 8. Now create an enum PersistenceManager for creating EntityManagerFactory and EntityManager

package com.roytuts.jpa.manager;

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

public enum PersistenceManager {

	_INSTANCE;

	private EntityManagerFactory emf;

	private PersistenceManager() {
		emf = Persistence.createEntityManagerFactory("userPersistanceUnit");
	}

	public EntityManager getEntityManager() {
		return emf.createEntityManager();
	}

	public void close() {
		emf.close();
	}

}

Step 9. Create a main class which will test the application.

package com.roytuts.jpa.crud.test;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import com.roytuts.jpa.entity.UserDetails;
import com.roytuts.jpa.exception.JpaException;
import com.roytuts.jpa.manager.PersistenceManager;

public class JpaCriteriaTest {

	public static void main(String[] args) {
		EntityManager em = PersistenceManager._INSTANCE.getEntityManager();

		try {
			em.getTransaction().begin();

			CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
			CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery();
			Root<UserDetails> from = criteriaQuery.from(UserDetails.class);

			// select all records
			System.out.println("Select all records");
			System.out.println("------------------");
			System.out.println();
			CriteriaQuery<Object> select = criteriaQuery.select(from);
			TypedQuery<Object> typedQuery = em.createQuery(select);
			List<Object> resultlist = typedQuery.getResultList();

			for (Object o : resultlist) {
				UserDetails u = (UserDetails) o;
				System.out.println("ID : " + u.getId() + " First Name : " + u.getFirstName() + " Last Name : "
						+ u.getLastName() + " Email : " + u.getEmail() + " DOB : " + u.getDob());
			}

			// Ordering the records
			System.out.println();
			System.out.println("Select all records in ascending order");
			System.out.println("-------------------------------------");
			System.out.println();
			CriteriaQuery<Object> select1 = criteriaQuery.select(from);
			select1.orderBy(criteriaBuilder.asc(from.get("firstName")));
			TypedQuery<Object> typedQuery1 = em.createQuery(select);
			List<Object> resultlist1 = typedQuery1.getResultList();
			for (Object o : resultlist1) {
				UserDetails u = (UserDetails) o;
				System.out.println("ID : " + u.getId() + " First Name : " + u.getFirstName() + " Last Name : "
						+ u.getLastName() + " Email : " + u.getEmail() + " DOB : " + u.getDob());
			}

			em.getTransaction().commit();
		} catch (JpaException e) {
			em.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			em.close();
			PersistenceManager._INSTANCE.close();
		}

		// update user for id 11
		try {
			UserDetails user = new UserDetails();
			user.setId(13);
			user.setFirstName("Liton");
			user.setLastName("Sarkar");
			user.setEmail("liton.sarkar@email.com");
			user.setDob("14-07-1990");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

Step 11. Create table user_details in MySQL database and dump some data into it

USE `cdcol`;

/*Table structure for table `user_details` */

DROP TABLE IF EXISTS `user_details`;

CREATE TABLE `user_details` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `first_name` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `last_name` varchar(15) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `dob` varchar(16) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
insert  into 
`user_details`(`id`,`first_name`,`last_name`,`email`,`dob`) 
values 
(7,'Soumitra','Roy','contact@roytuts.com','30-08-2016'),
(8,'Souvik','Sanyal','souvik.sanyal@email.com','30-09-1991'),
(13,'Liton','Sarkar','liton.sarkar@email.com','14-07-1990');

Step 12. Run the above main class, you will see below output in the console.

Select all records
------------------

Hibernate: 
    select
        userdetail0_.id as id1_6_,
        userdetail0_.dob as dob2_6_,
        userdetail0_.email as email3_6_,
        userdetail0_.first_name as first_na4_6_,
        userdetail0_.last_name as last_nam5_6_ 
    from
        user_details userdetail0_
ID : 7 First Name : Soumitra Last Name : Roy Email : contact@roytuts.com DOB : 30-08-2016
ID : 8 First Name : Souvik Last Name : Sanyal Email : souvik.sanyal@email.com DOB : 30-09-1991
ID : 13 First Name : Liton Last Name : Sarkar Email : liton.sarkar@email.com DOB : 14-07-1990

Select all records in ascending order
-------------------------------------

Hibernate: 
    select
        userdetail0_.id as id1_6_,
        userdetail0_.dob as dob2_6_,
        userdetail0_.email as email3_6_,
        userdetail0_.first_name as first_na4_6_,
        userdetail0_.last_name as last_nam5_6_ 
    from
        user_details userdetail0_ 
    order by
        userdetail0_.first_name asc
ID : 13 First Name : Liton Last Name : Sarkar Email : liton.sarkar@email.com DOB : 14-07-1990
ID : 7 First Name : Soumitra Last Name : Roy Email : contact@roytuts.com DOB : 30-08-2016
ID : 8 First Name : Souvik Last Name : Sanyal Email : souvik.sanyal@email.com DOB : 30-09-1991

Recommended Reading:

Spring Data JPA Specification Criteria Query Example

Hibernate Criteria API Example

Thanks for reading.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit | Email Me

Leave a Reply

Your email address will not be published. Required fields are marked *