Criteria API example in Hibernate

Introduction

Criteria is a simplified API for retrieving entities by composing Criterion objects. This is a very convenient approach for functionality like “search” screens where there is a variable number of conditions to be placed upon the result set.

We will configure hibernate using Java based configuration, for example, we will build SessionFactory with required configurations using Java code. So we won’t use any XML based configuration for this example.

Recommended Reading:

The following example shows how to work with Hibernate Criteria API.

Prerequisites

Eclipse 4.12, At least Java 8, Gradle 6.1.1, Maven 3.6.3, Hibernate 5.4.11

Create Table

We will create a table in MySQL server under database roytuts. The name of the table is items.

CREATE TABLE `items` (
  `item_id` int unsigned NOT NULL AUTO_INCREMENT,
  `item_name` varchar(45) NOT NULL,
  `item_desc` text,
  `item_price` double unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`item_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

We need to test our application right away, so we will dump some data into the above table.

insert  into `items`(`item_id`,`item_name`,`item_desc`,`item_price`) values
(1,'CD','CD is a compact disk',100),
(2,'DVD','DVD is larger than CD in size',150),
(3,'ABC','ABC test description',24),
(4,'XYZ','XYZ test description',25.32),
(5,'CD Player','CD player is used to play CD',30.02);

Create Project

Create gradle or maven based project in Eclipse. The name of the project is hibernate-criteria-api.

If you are creating gradle based project then you can use below build.gradle script:

plugins {
    id 'java-library'
}

sourceCompatibility = 12
targetCompatibility = 12

repositories {
    jcenter()
}

dependencies {
    implementation('org.hibernate:hibernate-core:5.4.11.Final')
    implementation('mysql:mysql-connector-java:8.0.17')
}

If you are creating maven based project then you can use below pom.xml file:

<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>hibernate-stored-procedure</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>5.4.11.Final</version>
		</dependency>
		
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.17</version>
		</dependency>
	</dependencies>

    <build>
        <plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>at least 8</source>
					<target>at least 8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Hibernate Configuration

Now we will configure hibernate using Java based as shown below:

package com.roytuts.hibernate.criteria.api.utils;

import java.util.Properties;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;

import com.roytuts.hibernate.criteria.api.entity.Item;

public class HibernateUtil {

	private static SessionFactory sessionFactory;

	public static SessionFactory getSessionFactory() {

		if (sessionFactory == null) {
			try {
				Properties settings = new Properties();

				settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
				settings.put(Environment.URL, "jdbc:mysql://localhost:3306/roytuts");
				settings.put(Environment.USER, "root");
				settings.put(Environment.PASS, "root");
				settings.put(Environment.DIALECT, "org.hibernate.dialect.MySQLDialect");
				settings.put(Environment.SHOW_SQL, "true");
				settings.put(Environment.FORMAT_SQL, "true");
				settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");

				Configuration configuration = new Configuration();
				configuration.setProperties(settings);

				configuration.addAnnotatedClass(Item.class);

				ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
						.applySettings(configuration.getProperties()).build();

				sessionFactory = configuration.buildSessionFactory(serviceRegistry);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return sessionFactory;
	}

}

Entity Class

The entity class is responsible to map the Java attributes with table columns in database.

package com.roytuts.hibernate.criteria.api.entity;

import java.io.Serializable;

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 = "items")
public class Item implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@Column(name = "item_id")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;

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

	@Column(name = "item_desc")
	private String desc;

	@Column(name = "item_price")
	private double price;

	public Integer getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Item [id=" + id + ", name=" + name + ", desc=" + desc + ", price=" + price + "]";
	}

}

Work on Criteria API

Now we will work on Hibernate Criteria API.

The first example will show you how to retrieve all records from the table using Criteria API. In Hibernate 5, the syntax of the Criteria API has been changed significantly.

CriteriaBuilder builder = session.getCriteriaBuilder();

CriteriaQuery<Item> criteria = builder.createQuery(Item.class);
criteria.from(Item.class);

List<Item> items = session.createQuery(criteria).getResultList();

Running the above code snippets will give you the following output:

Hibernate: 
    select
        item0_.item_id as item_id1_0_,
        item0_.item_desc as item_des2_0_,
        item0_.item_name as item_nam3_0_,
        item0_.item_price as item_pri4_0_ 
    from
        items item0_
Item [id=1, name=CD, desc=CD is a compact disk, price=100.0]
Item [id=2, name=DVD, desc=DVD is larger than CD in size, price=150.0]
Item [id=3, name=ABC, desc=ABC test description, price=24.0]
Item [id=4, name=XYZ, desc=XYZ test description, price=25.32]
Item [id=5, name=CD Player, desc=CD player is used to play CD, price=30.02]

If you want to limit max result then you can do so using setMaxResult(int max) method.

List<Item> items = session.createQuery(criteria).setMaxResults(3).getResultList();

So the above code returns maximum number of 3 items if there are more than 3 items as shown below in the output:

Hibernate: 
    select
        item0_.item_id as item_id1_0_,
        item0_.item_desc as item_des2_0_,
        item0_.item_name as item_nam3_0_,
        item0_.item_price as item_pri4_0_ 
    from
        items item0_ limit ?
Item [id=1, name=CD, desc=CD is a compact disk, price=100.0]
Item [id=2, name=DVD, desc=DVD is larger than CD in size, price=150.0]
Item [id=3, name=ABC, desc=ABC test description, price=24.0]

You can perform Like search using below query. For example we want to return the rows for which we have item description like CD.

Root<Item> root = criteria.from(Item.class);
criteria.where(builder.like(root.get("desc"), "%CD%"));
List<Item> items = session.createQuery(criteria).getResultList();
items.stream().forEach(i -> System.out.println(i));

 Running the above code snippets will give you below output:

Hibernate: 
    select
        item0_.item_id as item_id1_0_,
        item0_.item_desc as item_des2_0_,
        item0_.item_name as item_nam3_0_,
        item0_.item_price as item_pri4_0_ 
    from
        items item0_ 
    where
        item0_.item_desc like ?
Item [id=1, name=CD, desc=CD is a compact disk, price=100.0]
Item [id=2, name=DVD, desc=DVD is larger than CD in size, price=150.0]
Item [id=5, name=CD Player, desc=CD player is used to play CD, price=30.02]

You can restrict the result list between a range of values. For example we want to fetch rows for items having id between 2 and 4.

Root<Item> root = criteria.from(Item.class);
criteria.where(builder.between(root.get("id"), 2, 4));
List<Item> items = session.createQuery(criteria).getResultList();
items.stream().forEach(i -> System.out.println(i));

Running the above code snippets will give you below output:

Hibernate: 
    select
        item0_.item_id as item_id1_0_,
        item0_.item_desc as item_des2_0_,
        item0_.item_name as item_nam3_0_,
        item0_.item_price as item_pri4_0_ 
    from
        items item0_ 
    where
        item0_.item_id between 2 and 4
Item [id=2, name=DVD, desc=DVD is larger than CD in size, price=150.0]
Item [id=3, name=ABC, desc=ABC test description, price=24.0]
Item [id=4, name=XYZ, desc=XYZ test description, price=25.32]

Ordering the results either by ascending or descending.

Let’s say we want to retrieve the rows based on price in ascending order.

Root<Item> root = criteria.from(Item.class);
criteria.orderBy(builder.asc(root.get("price")));
List<Item> items = session.createQuery(criteria).getResultList();
items.stream().forEach(i -> System.out.println(i));

Running the above code snippets will give you the following output:

Hibernate: 
    select
        item0_.item_id as item_id1_0_,
        item0_.item_desc as item_des2_0_,
        item0_.item_name as item_nam3_0_,
        item0_.item_price as item_pri4_0_ 
    from
        items item0_ 
    order by
        item0_.item_price asc
Item [id=3, name=ABC, desc=ABC test description, price=24.0]
Item [id=4, name=XYZ, desc=XYZ test description, price=25.32]
Item [id=5, name=CD Player, desc=CD player is used to play CD, price=30.02]
Item [id=1, name=CD, desc=CD is a compact disk, price=100.0]
Item [id=2, name=DVD, desc=DVD is larger than CD in size, price=150.0]

Let’s say we want to retrieve the rows based on id field in descending order.

Root<Item> root = criteria.from(Item.class);
criteria.orderBy(builder.desc(root.get("id")));
List<Item> items = session.createQuery(criteria).getResultList();
items.stream().forEach(i -> System.out.println(i));

Executing the above code snippets will give you the following output:

Hibernate: 
    select
        item0_.item_id as item_id1_0_,
        item0_.item_desc as item_des2_0_,
        item0_.item_name as item_nam3_0_,
        item0_.item_price as item_pri4_0_ 
    from
        items item0_ 
    order by
        item0_.item_id desc
Item [id=5, name=CD Player, desc=CD player is used to play CD, price=30.02]
Item [id=4, name=XYZ, desc=XYZ test description, price=25.32]
Item [id=3, name=ABC, desc=ABC test description, price=24.0]
Item [id=2, name=DVD, desc=DVD is larger than CD in size, price=150.0]
Item [id=1, name=CD, desc=CD is a compact disk, price=100.0]

Here is how to restrict the results by equality check.

Root<Item> root = criteria.from(Item.class);
criteria.where(builder.equal(root.get("name"), "CD"));
List<Item> items = session.createQuery(criteria).getResultList();
items.stream().forEach(i -> System.out.println(i));

Executing the above code snippets will give you the following output:

Hibernate: 
    select
        item0_.item_id as item_id1_0_,
        item0_.item_desc as item_des2_0_,
        item0_.item_name as item_nam3_0_,
        item0_.item_price as item_pri4_0_ 
    from
        items item0_ 
    where
        item0_.item_name=?
Item [id=1, name=CD, desc=CD is a compact disk, price=100.0]

There are many options using Criteria API to restrict your results based on different parameters but this tutorial only shows very few of them how to work with Criteria API in Hibernate framework.

Source Code

Download

Thanks for reading.

Leave a Comment