📘 Goal
To build a Spring Boot application that performs dynamic OR-based filtering with pagination using Spring Data JPA in three different ways:
- Using
@Query
annotation - Using
CriteriaBuilder
API - 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".