GitHunt
HA

harman-04/spring-data-jpa-criteria-specifications

A demonstration of building dynamic, type-safe database queries using JPA Criteria API and Spring Data Specifications in Spring Boot 4.0.1.

Programmatic Querying: JPA Criteria API & Specifications

Project Overview

In real-world applications (like an e-commerce filter sidebar), the user might search by name, price, or both. Writing static HQL for every possible combination is impossible. This project uses the JPA Criteria API wrapped in Spring Data JPA Specifications to build these complex queries dynamically based on runtime conditions.


Technical Concepts

1. Criteria API Components

The Criteria API uses three main objects to construct a query:

  • Root: The entity you are querying (e.g., Employee). It allows you to access class properties.
  • CriteriaQuery: The top-level query object where you define what to select (e.g., SELECT e).
  • CriteriaBuilder: The factory used to create "Predicates" (the WHERE clause conditions like greaterThan or like).

2. Spring Data JPA Specifications

The raw Criteria API is very verbose. Spring Data's Specification interface simplifies this by allowing you to write reusable "blocks" of query logic that can be combined using and(), or(), and not().

3. Type-Safety

Unlike HQL or Native SQL, Specifications are built using Java code. If you rename a field in your entity, your IDE and compiler will immediately flag errors in your Specifications, making your codebase much easier to maintain and refactor.


Component Reference

EmployeeRepository.java

By extending JpaSpecificationExecutor<Employee>, the repository gains a new set of methods like findAll(Specification spec), which can accept the dynamic query logic we build.

EmployeeSpecifications.java

This is a utility class containing static factory methods.

  • hasSalaryGreaterThan: Creates a predicate for salary filtering.
  • nameContains: Creates a predicate for partial name matching using the % wildcard.

CriteriaLearningRunner.java

This class demonstrates the "Lego-like" nature of Specifications:

Specification<Employee> spec = Specification
        .where(EmployeeSpecifications.hasSalaryGreaterThan(50000))
        .and(EmployeeSpecifications.nameContains("a"));

Hibernate takes this object and dynamically generates a single SQL query:
SELECT * FROM employees WHERE salary > 50000 AND name LIKE '%a%';


Key Advantages

Feature Query Methods HQL/JPQL Criteria/Specs
Simplicity High Medium Low
Dynamic Filters Hard Medium High
Type Safety Yes No Yes

How to Test

  1. DB Setup: Ensure your MySQL database is active.
  2. Run: Start the JpaCriteriaApiApplication.
  3. Analyze Console:
  • The application will first save 5 employees.
  • It will then print only those who earn more than 50k AND have the letter 'a' in their name.
  • Example Output:
--- Criteria API Filter Results ---
Raju Kumar - 60000.0
Syam - 85000.0


Output

Hibernate: 
    create table employees (
        id bigint not null auto_increment,
        name varchar(255),
        salary float(53) not null,
        primary key (id)
    ) engine=InnoDB
2026-01-18T23:06:32.976+05:30  INFO 18784 --- [jpa-criteria-api] [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2026-01-18T23:06:33.070+05:30  INFO 18784 --- [jpa-criteria-api] [  restartedMain] o.s.d.j.r.query.QueryEnhancerFactories   : Hibernate is in classpath; If applicable, HQL parser will be used.
2026-01-18T23:06:33.216+05:30  WARN 18784 --- [jpa-criteria-api] [  restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2026-01-18T23:06:33.619+05:30  INFO 18784 --- [jpa-criteria-api] [  restartedMain] o.s.boot.tomcat.TomcatWebServer          : Tomcat started on port 8080 (http) with context path '/'
2026-01-18T23:06:33.627+05:30  INFO 18784 --- [jpa-criteria-api] [  restartedMain] c.j.JpaCriteriaApiApplication            : Started JpaCriteriaApiApplication in 10.97 seconds (process running for 11.726)
Hibernate: 
    insert 
    into
        employees
        (name, salary) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        employees
        (name, salary) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        employees
        (name, salary) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        employees
        (name, salary) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        employees
        (name, salary) 
    values
        (?, ?)
Hibernate: 
    select
        e1_0.id,
        e1_0.name,
        e1_0.salary 
    from
        employees e1_0 
    where
        e1_0.salary>? 
        and e1_0.name like ? escape ''
--- Criteria API Filter Results ---
Raju Kumar-60000.0
Eswar-75000.0
Jagan-55000.0
Syam-85000.0