middle
Criteria API — что это и когда использовать?
Criteria API — программный (type-safe) способ построения запросов в JPA. В отличие от JPQL (строковые запросы), Criteria API использует Java-объекты для построения запроса, что обеспечивает проверку на этапе компиляции.
Базовый пример
Пример
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
// SELECT u FROM User u WHERE u.status = 'ACTIVE' AND u.name LIKE '%John%'
query.select(user)
.where(
cb.and(
cb.equal(user.get("status"), UserStatus.ACTIVE),
cb.like(user.get("name"), "%John%")
)
)
.orderBy(cb.asc(user.get("name")));
List<User> result = entityManager.createQuery(query).getResultList();
Динамические запросы — основное преимущество
Пример динамического фильтра
public List<User> search(String name, UserStatus status, String email) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
List<Predicate> predicates = new ArrayList<>();
if (name != null) {
predicates.add(cb.like(cb.lower(user.get("name")), "%" + name.toLowerCase() + "%"));
}
if (status != null) {
predicates.add(cb.equal(user.get("status"), status));
}
if (email != null) {
predicates.add(cb.equal(user.get("email"), email));
}
query.where(predicates.toArray(new Predicate[0]));
return entityManager.createQuery(query).getResultList();
}
Spring Data JPA Specification (обёртка над Criteria API)
Пример Specification
public class UserSpecifications {
public static Specification<User> hasName(String name) {
return (root, query, cb) -> cb.like(cb.lower(root.get("name")), "%" + name.toLowerCase() + "%");
}
public static Specification<User> hasStatus(UserStatus status) {
return (root, query, cb) -> cb.equal(root.get("status"), status);
}
}
// Использование
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {}
List<User> users = userRepository.findAll(
Specification.where(UserSpecifications.hasName("John"))
.and(UserSpecifications.hasStatus(UserStatus.ACTIVE))
);
Важное
- Criteria API — type-safe построение запросов через Java-объекты
- Основное преимущество — динамические запросы с переменным набором условий
- Для статических запросов JPQL проще и читаемее
- Spring Data Specification — удобная обёртка над Criteria API
Частые ошибки
- Использовать Criteria для простых запросов — JPQL намного читаемее для статических запросов
- Строки вместо Metamodel —
user.get("name")не проверяется компилятором; опечатка обнаружится только в runtime - Не подключить Metamodel Generator — без
User_теряется основное преимущество type-safety
Как используется в 2026
- Spring Data Specification — стандарт для динамических фильтров в REST API
- QueryDSL — популярная альтернатива Criteria API с более читаемым синтаксом (но проблемы с поддержкой Jakarta)
- Для сложных запросов — jOOQ набирает популярность как type-safe альтернатива
На собеседовании: Criteria API — для динамических запросов, JPQL — для статических. Упомяните Spring Data Specification как удобную обёртку. Если спросят про type-safety — расскажите про JPA Static Metamodel Generator (User_). QueryDSL — альтернатива с лучшим синтаксисом.