Hibernate Criteria API
What is the Criteria API?
The JPA Criteria API provides a type-safe, programmatic way to build queries. Unlike HQL (string-based), Criteria queries are built using Java objects and are checked at compile time — typos in property names cause compile errors, not runtime errors.
The Criteria API is especially useful for building dynamic queries where the conditions are not known at compile time (e.g., search filters).
import jakarta.persistence.criteria.*;
Session session = sessionFactory.openSession();
// Get CriteriaBuilder from session
CriteriaBuilder cb = session.getCriteriaBuilder();
// Create CriteriaQuery for User
CriteriaQuery<User> cq = cb.createQuery(User.class);
// Define the root entity (FROM User u)
Root<User> root = cq.from(User.class);
// SELECT * FROM users (no WHERE)
cq.select(root);
List<User> allUsers = session.createQuery(cq).getResultList();
// WHERE u.role = 'ADMIN'
Predicate roleAdmin = cb.equal(root.get("role"), "ADMIN");
cq.where(roleAdmin);
List<User> admins = session.createQuery(cq).getResultList();
// WHERE u.age >= 18 AND u.active = true
Predicate ageCheck = cb.greaterThanOrEqualTo(root.get("age"), 18);
Predicate activeCheck = cb.isTrue(root.get("active"));
cq.where(cb.and(ageCheck, activeCheck));
// ORDER BY u.lastName ASC
cq.orderBy(cb.asc(root.get("lastName")));
// Execute
List<User> result = session.createQuery(cq).getResultList();
session.close();
// Dynamic search query - conditions added based on non-null parameters
public List<User> searchUsers(String name, String email, String role,
int page, int pageSize) {
Session session = sessionFactory.openSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> root = cq.from(User.class);
List<Predicate> predicates = new ArrayList<>();
// Add conditions only if parameters are provided
if (name != null && !name.isEmpty()) {
predicates.add(cb.like(cb.lower(root.get("username")),
"%" + name.toLowerCase() + "%"));
}
if (email != null && !email.isEmpty()) {
predicates.add(cb.like(root.get("email"), "%" + email + "%"));
}
if (role != null && !role.isEmpty()) {
predicates.add(cb.equal(root.get("role"), role));
}
// Combine all predicates with AND
if (!predicates.isEmpty()) {
cq.where(cb.and(predicates.toArray(new Predicate[0])));
}
cq.orderBy(cb.asc(root.get("username")));
// Pagination
List<User> results = session.createQuery(cq)
.setFirstResult(page * pageSize) // Offset
.setMaxResults(pageSize) // Limit
.getResultList();
session.close();
return results;
}
// Count query for pagination
public Long countUsers(String role) {
Session session = sessionFactory.openSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<User> root = cq.from(User.class);
cq.select(cb.count(root));
if (role != null) {
cq.where(cb.equal(root.get("role"), role));
}
Long count = session.createQuery(cq).uniqueResult();
session.close();
return count;
}
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.