Specifications

Базовый Spring
≈ 1 мин чтения

Динамический поиск из небольших условий

Представим экран поиска, где пользователь может независимо указать статус, имя, минимальный возраст и другие фильтры. Создавать отдельный метод репозитория для каждой комбинации быстро становится неудобно. В Spring Data JPA для таких случаев есть Specification — объект, описывающий одно условие запроса.

interface CustomerRepository
        extends JpaRepository<Customer, Long>,
                JpaSpecificationExecutor<Customer> {
}

Specification<Customer> active =
        (root, query, cb) -> cb.isTrue(root.get("active"));

Specification<Customer> adult =
        (root, query, cb) -> cb.greaterThanOrEqualTo(root.get("age"), 18);

List<Customer> customers = repository.findAll(active.and(adult));

Каждая спецификация описывает небольшой предикат. Интерфейс JpaSpecificationExecutor добавляет методы, которые умеют выполнять такие условия, а спецификации можно объединять через and, or и отрицание.

Когда Specifications особенно полезны

Они хорошо подходят для фильтров, набор которых определяется во время выполнения: например, часть полей поисковой формы может быть заполнена, а часть — нет. Код может добавить только нужные условия и затем передать готовую комбинацию репозиторию.

Specification строится на Criteria API. Поэтому вместо SQL-строки код работает с моделью сущности и объектами критериев JPA. Для простого фиксированного запроса derived query или @Query обычно читается легче.