JPA Criteria Queries | Code Factory
Reference Link : Link
Donate : Link
1. Overview
A very useful JPA feature — Criteria Queries.
It not only enables us to write queries without doing raw SQL, but also gives us some Object Oriented control over the queries, which is one of the main features of Hibernate. The Criteria API allows us to build up a criteria query object programmatically, where we can apply different kind of filtration rules and logical conditions.
Since Hibernate 5.2, the Hibernate Criteria API is deprecated and new development is focused on the JPA Criteria API. We’ll explore how to use Hibernate and JPA to build Criteria Queries.
2. Maven Dependencies
To illustrate the API, we’ll use the reference JPA implementation — Hibernate.
To use Hibernate make sure you add the latest version of it to your pom.xml
file :
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.2.Final</version>
</dependency>
The latest version of Hibernate can be found here.
3. Simple Example Using Criteria
Let’s start by looking at how to retrieve data using Criteria queries. We’ll have a look at how to get all the instances of a particular class from the database.
We have an Item
class which represents the tuple “ITEM”
in the database :
public class Item implements Serializable {
private Integer itemId;
private String itemName;
private String itemDescription;
private Integer itemPrice;
// setters and getters
}
Let’s look at a simple criteria query which will retrieve all the rows of “ITEM”
from the database :
Session session = HibernateUtil.getHibernateSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Item> cr = cb.createQuery(Item.class);
Root<Item> root = cr.from(Item.class);
cr.select(root);
Query<Item> query = session.createQuery(cr);
List<Item> results = query.getResultList();
The above query is a simple demonstration of how to get all the items. Let’s see what was done, step by step :
- Create an instance of
Session
from theSessionFactory
object - Create an instance of
CriteriaBuilder
by calling thegetCriteriaBuilder()
method - Create an instance of
CriteriaQuery
by calling theCriteriaBuilder
createQuery()
method - Create an instance of
Query
by calling theSession createQuery()
method - Call the
getResultList()
method of thequery
object which gives us the results
3.1. Using Expressions
The CriteriaBuilder can be used to restrict query results based on specific conditions. By using CriteriaQuery where()
method and provide Expressions
created by CriteriaBuilder.
To get items having a price more than 1000 :
cr.select(root).where(cb.gt(root.get("itemPrice"), 1000));
Next, getting items having itemPrice
less than 1000 :
cr.select(root).where(cb.lt(root.get("itemPrice"), 1000));
Items having itemNames
contain Chair
:
cr.select(root).where(cb.like(root.get("itemName"), "%chair%"));
Records having itemPrice
in between 100 and 200 :
cr.select(root).where(cb.between(root.get("itemPrice"), 100, 200));
To check if the given property is null :
cr.select(root).where(cb.isNull(root.get("itemDescription")));
To check if the given property is not null :
cr.select(root).where(cb.isNotNull(root.get("itemDescription")));
You can also use the methods isEmpty()
and isNotEmpty()
to test if a List
within a class is empty or not.
We can also combine two or more of the above comparisons. The Criteria API allows us to easily chain expressions :
Predicate[] predicates = new Predicate[2];
predicates[0] = cb.isNull(root.get("itemDescription"));
predicates[1] = cb.like(root.get("itemName"), "chair%");
cr.select(root).where(predicates);
To add two expressions with logical operations :
Predicate greaterThanPrice = cb.gt(root.get("itemPrice"), 1000);
Predicate chairItems = cb.like(root.get("itemName"), "Chair%");
Items with the above-defined conditions joined with Logical OR :
cr.select(root).where(cb.or(greaterThanPrice, chairItems));
To get items matching with the above-defined conditions joined with Logical AND :
cr.select(root).where(cb.and(greaterThanPrice, chairItems));
3.2. Sorting
Now that we know the basic usage of Criteria
, let’s have a look at the sorting functionalities of Criteria
.
In the following example we order the list in an ascending order of the name and then in a descending order of the price :
cr.orderBy(
cb.asc(root.get("itemName")),
cb.desc(root.get("itemPrice")));
3.3. Projections, Aggregates And Grouping Functions
Let’s have a look at the different aggregate functions :
Get row count :
CriteriaQuery<Long> cr = cb.createQuery(Long.class);
Root<Item> root = cr.from(Item.class);
cr.select(cb.count(root));
Query<Long> query = session.createQuery(cr);
List<Long> itemProjected = query.getResultList();
The following is an example of aggregate functions:
Aggregate
function for Average
:
CriteriaQuery<Double> cr = cb.createQuery(Double.class);
Root<Item> root = cr.from(Item.class);
cr.select(cb.avg(root.get("itemPrice")));
Query<Double> query = session.createQuery(cr);
List avgItemPriceList = query.getResultList();
Other useful aggregate methods that are available are sum()
, max()
, min()
, count()
etc.
3.4. CriteriaUpdate
Starting from JPA 2.1, there’s support for performing database updates using the Criteria API.
CriteriaUpdate
has a set()
method that can used to provide new values for database records :
CriteriaUpdate<Item> criteriaUpdate = cb.createCriteriaUpdate(Item.class);
Root<Item> root = criteriaUpdate.from(Item.class);
criteriaUpdate.set("itemPrice", newPrice);
criteriaUpdate.where(cb.equal(root.get("itemPrice"), oldPrice));
Transaction transaction = session.beginTransaction();
session.createQuery(criteriaUpdate).executeUpdate();
transaction.commit();
3.5. CriteriaDelete
CriteriaDelete,
as its name implies, enables a delete operation using the Criteria API. All we need is to create an instance of CriteriaDelete
and use the where()
method to apply restrictions :
CriteriaDelete<Item> criteriaDelete = cb.createCriteriaDelete(Item.class);
Root<Item> root = criteriaDelete.from(Item.class);
criteriaDelete.where(cb.greaterThan(root.get("itemPrice"), targetPrice));
Transaction transaction = session.beginTransaction();
session.createQuery(criteriaDelete).executeUpdate();
transaction.commit();