Рубрики
Без рубрики

Конструктор условных критериев для необязательных параметров

Условные запросы к базе данных со спецификацией JPA. С тегами java, spring, спецификация, база данных.

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

Эта задача была легко (как только я понял это) решена с помощью спецификаций JPA.

Посмотрите на следующий пример, где я буду использовать поля данных, скажем, для… участников дня рождения:

public Specification filterAttendees(Optional firstNameFilter, Optional lastNameFilter) {

    return (root, criteriaQuery, criteriaBuilder) -> {
        List
 predicates = new ArrayList<>();
        if (firstNameFilter.isPresent() && (firstNameFilter.get().length() > 0)) {
            predicates.add(criteriaBuilder.and(criteriaBuilder.like(criteriaBuilder.lower(root.get("firstName")), "%" + firstNameFilter.get().toLowerCase() + "%")));
        }
        if (lastNameFilter.isPresent() &&(lastNameFilter.get().length() > 0)) {
            predicates.add(criteriaBuilder.and(criteriaBuilder.like(criteriaBuilder.lower(root.get("lastName")), "%" + lastNameFilter.get().toLowerCase() + "%")));
        }

        return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
    };
}

В приведенном выше примере будет выбран любой Участник, чье имя ПОХОЖЕ на указанную строку. Вот как это делается:

  • Метод принимает два необязательных параметра, что означает, что я могу предоставить оба, один или ни один из них. Я расскажу об этом подробнее ближе к концу.

  • Строка return (root, CriteriaQuery, CriteriaBuilder) -> передает корневого участника, запрос к базе данных и критерии, которые вы создаете для выполнения указанного запроса. Я написал это как lamba для краткости, но более старая форма написания спецификации () также будет работать.

  • Я создаю список предикатов, которые будут объединены в мой конструктор критериев, чтобы создать полный набор критериев. Как и в английском языке, сказуемое здесь является основой или значением полного выражения. Вы увидите в последней строке, что я добавляю все это вместе в предикат единственного числа и использую его для создания моего CriteriaBuilder, который я возвращаю.

  • Основная часть всего этого сегмента кода, и то, что делает его действительно условным, - это два похожих оператора, которые проверяют, что filter .isPresent () и не пустой (что длина больше 0). Если эти условия выполнены, я знаю, что моему методу были переданы параметры, которые необходимо включить в мой поиск. Как только они у меня появятся, я смогу указать CriteriaBuilder найти ПОДОБНЫЕ экземпляры в базе данных и включить их в CriteriaBuilder.

  • Наличие этих необязательных параметров - это то, что действительно позволяет этому методу быть динамичным. Поскольку я учитываю вероятность того, что параметр имеет значение null, я могу использовать этот метод для поиска участников по полному имени, только по имени или только по фамилии. Я даже могу настроить это так, чтобы возвращать всех участников, если параметры должны были вернуться полностью пустыми. Этот метод был бы надежным и исключал бы множество пользовательских ошибок и некоторую проверку формы на интерфейсе.

Спасибо за ваше время, и я надеюсь, что вы найдете этому применение!

Оригинал: "https://dev.to/bowlendev/conditional-criteriabuilder-for-optional-params-2j6"