Programming & Development / April 18, 2025

Spring Data JPA Dynamic OR Clause with Pagination in Spring Boot

Spring Boot JPA dynamic query OR clause CriteriaBuilder Specifications pagination Pageable @Query

📘 Goal

To build a Spring Boot application that performs dynamic OR-based filtering with pagination using Spring Data JPA in three different ways:

  1. Using @Query annotation
  2. Using CriteriaBuilder API
  3. Using Specification interface

🧱 Entity Example

java

// User.java
import jakarta.persistence.*;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;
    private String lastName;

    // Getters and setters
}

1️⃣ Using @Query with Pagination

Repository

java

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.*;
import org.springframework.data.repository.query.Param;

public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.firstName = :firstName OR u.lastName = :lastName")
    Page<User> findByFirstNameOrLastName(
        @Param("firstName") String firstName,
        @Param("lastName") String lastName,
        Pageable pageable
    );
}

Service

java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public Page<User> findByFirstNameOrLastName(String firstName, String lastName, int page, int size) {
        return userRepository.findByFirstNameOrLastName(firstName, lastName, PageRequest.of(page, size));
    }
}

2️⃣ Using CriteriaBuilder with Pagination

java

import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import jakarta.persistence.*;
import jakarta.persistence.criteria.*;
import java.util.*;

@Service
public class UserService {

    @PersistenceContext
    private EntityManager entityManager;

    public Page<User> findByFirstNameOrLastName(String firstName, String lastName, Pageable pageable) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();

        // Data Query
        CriteriaQuery<User> query = cb.createQuery(User.class);
        Root<User> user = query.from(User.class);

        List<Predicate> predicates = new ArrayList<>();
        if (firstName != null) predicates.add(cb.equal(user.get("firstName"), firstName));
        if (lastName != null) predicates.add(cb.equal(user.get("lastName"), lastName));

        query.select(user).where(cb.or(predicates.toArray(new Predicate[0])));

        List<User> users = entityManager.createQuery(query)
                .setFirstResult((int) pageable.getOffset())
                .setMaxResults(pageable.getPageSize())
                .getResultList();

        // Count Query
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<User> countRoot = countQuery.from(User.class);
        countQuery.select(cb.count(countRoot))
                .where(cb.or(predicates.toArray(new Predicate[0])));
        Long total = entityManager.createQuery(countQuery).getSingleResult();

        return new PageImpl<>(users, pageable, total);
    }
}

3️⃣ Using Specification with Pagination

Specification

java

import org.springframework.data.jpa.domain.Specification;
import jakarta.persistence.criteria.*;

import java.util.*;

public class UserSpecification {

    public static Specification<User> hasFirstNameOrLastName(String firstName, String lastName) {
        return (Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (firstName != null) predicates.add(cb.equal(root.get("firstName"), firstName));
            if (lastName != null) predicates.add(cb.equal(root.get("lastName"), lastName));
            return cb.or(predicates.toArray(new Predicate[0]));
        };
    }
}

Repository

java

import org.springframework.data.jpa.repository.*;

public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
}

Service

java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public Page<User> findByFirstNameOrLastName(String firstName, String lastName, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userRepository.findAll(UserSpecification.hasFirstNameOrLastName(firstName, lastName), pageable);
    }
}

🚀 Example Usage

java

Page<User> result = userService.findByFirstNameOrLastName("John", "Doe", 0, 10);

This will retrieve up to 10 users whose first name is "John" or last name is "Doe".


Comments

No comments yet

Add a new Comment

NUHMAN.COM

Information Technology website for Programming & Development, Web Design & UX/UI, Startups & Innovation, Gadgets & Consumer Tech, Cloud Computing & Enterprise Tech, Cybersecurity, Artificial Intelligence (AI) & Machine Learning (ML), Gaming Technology, Mobile Development, Tech News & Trends, Open Source & Linux, Data Science & Analytics

Categories

Tags

©{" "} Nuhmans.com . All Rights Reserved. Designed by{" "} HTML Codex