Criteria Builder in Spring Data JPA

In this blog, I have posted, what is criteria builder in spring data JPA. Here you can learn what is criteia builder and where you can use it. And how can you use it.

Criteria Builder

Criteria builder is a part of spring data JPA.It provides many ways to retrieve the data from the table as entity objects. You can use Typed Query, JPQL, native SQL, or you can use in-build method in the JPA repository (findById, findAll). Criteria builder is working along the Entity Manager. The entity manager loads all the classes which are annotated with the @Entity at the time of application initialization.

You can use the criteria builder when you want to, dynamically generate the entity based select query and robotically. Your entity class may have the multiple properties. When you want to select the record by id you can use findbyId, but when you want to select the records by other properties, you have to create method for it. Here you can’t to add the multiple methods and you can’t to write a native SQL, or JPQL to select record by dynamic properties.

Example, If you have the manage order screen, there you should provide the multiple filter options, like filter by order status, order data, discount, product, delivery status etc. In this case you can’t to add the multiple methods. And it is not good practice. So in that case you can use the Criteria builder.

Normally Criteria Builder using for to construct criteria queries, compound selections, expressions, predicates, orderings. Note: Predicate is used instead of Expression in this API in order to work around the fact that Java generics are not compatible with var arguments.

Here you can see the sample code to select the list of object using Criteria Builder. Before you start this you should know that JPA configuration and JPA Repository, if you are not aware of it, please check here https://samplecoder.com/spring-boot-jpa-configuration/ And this blog is continuations of Spring Boot JPA Configuration Blog please make sure that you have that same sample code in your local for easy understanding.

Service & Service Implementation

package com.samplecoder.emo.service;

import java.util.List;

import com.samplecoder.emo.entity.Student;

public interface StudentService {

	List<Student> listAllStudents(Student student);
}
package com.samplecoder.emo.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.samplecoder.emo.custom.repository.CustomStudentRepository;
import com.samplecoder.emo.entity.Student;
import com.samplecoder.emo.service.StudentService;

@Service
public class StudentServiceImpl implements StudentService{
	
	@Autowired
	private CustomStudentRepository customStudentRepository;

	@Override
	public List<Student> listAllStudents(Student student) {
		// TODO Auto-generated method stub
		return customStudentRepository.listAllStudents(student);
	}

}

Custom Repository and Repository Implementation

package com.samplecoder.emo.custom.repository;

import java.util.List;

import com.samplecoder.emo.entity.Student;

public interface CustomStudentRepository {

	List<Student> listAllStudents(Student student);

}
package com.samplecoder.emo.custom.repository;

import java.util.ArrayList;
import java.util.List;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.samplecoder.emo.entity.Student;

@Repository
public class CustomStudentRepositoryImpl implements CustomStudentRepository {
	
	@Autowired
	private EntityManager entityManager;

	@Override
	public List<Student> listAllStudents(Student student) {
		// TODO Auto-generated method stub
		
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaQuery<Student> criteriaQuery = criteriaBuilder.createQuery(Student.class);
		Root<Student> root = criteriaQuery.from(Student.class);
		
		if(student != null) {
			List<Predicate> predicates = new ArrayList<Predicate>();
			
			if(student.getName() != null && !student.getName().isEmpty())
				predicates.add(criteriaBuilder.like(root.get("name"), student.getName()+"%"));
			
			if(student.getStd() > 0)
				predicates.add(criteriaBuilder.equal(root.get("std"), student.getStd()));
			
			criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
		}
		
		return entityManager.createQuery(criteriaQuery).getResultList();
	}

}

Controller

package com.samplecoder.emo.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.samplecoder.emo.entity.Student;
import com.samplecoder.emo.exceptions.StudentNotFoundException;
import com.samplecoder.emo.repository.StudentRepository;
import com.samplecoder.emo.service.StudentService;

@RestController
@RequestMapping("/api/student")
public class StudentController {
	

	@Autowired
	private StudentService studentService;

	
	@PostMapping("/listAll")
	private List<Student> listAll(@RequestBody Student student){
		return studentService.listAllStudents(student);
	}
}

Postman Response

Request URL: http://localhost:8080/api/student/listAll
Request Body: {}
//Get all students without adding any criteria
Response:
[
    {
        "id": 2,
        "name": "Muthu",
        "std": 12
    },
    {
        "id": 3,
        "name": "Hema",
        "std": 12
    },
    {
        "id": 4,
        "name": "Prajith",
        "std": 1
    },
    {
        "id": 5,
        "name": "Heshika",
        "std": 1
    },
    {
        "id": 6,
        "name": "Mugilan",
        "std": 11
    },
    {
        "id": 7,
        "name": "Shanmugam",
        "std": 11
    },
    {
        "id": 8,
        "name": "VInoth",
        "std": 10
    }
]
Request URL: http://localhost:8080/api/student/listAll
Request Body: {"std":10}
//Get all student those who are studying 10th Std
Response: 
[
    {
        "id": 8,
        "name": "VInoth",
        "std": 10
    }
]