Недавно я столкнулся с интересной задачей на работе, где мне нужно было условно запрашивать данные на основе ряда необязательных полей — то есть мне нужно было запрашивать то, что было запрошено, и ничего больше.
Эта задача была легко (как только я понял это) решена с помощью спецификаций JPA.
Посмотрите на следующий пример, где я буду использовать поля данных, скажем, для… участников дня рождения:
public SpecificationfilterAttendees(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"