В задаче по реализации фильтра, столкнулся с следующей проблемой. У фильтра есть некоторое колличество полей, которые в случае если пользователь оставил их пустыми, на сервер, в объект фильтра, прилетают как null. А при запросе в базу, мне надо получить объект org.springframework.data.jpa.domain.Specifications, который представит этот фильтр на SQL территории. Я хотел использовать следующую конструкцию для формирования объекта Specifications:
public Page<Phone> list(@NonNull Filter filter) {
Specifications<Phone> specifications = where(equal("id", filter.getId()))
.and(isBetween("regDate", filter.getRegFrom(), filter.getRegTo()))
.and(contain("operatorAccPassword", filter.getOpPassword()))
.and(contain("operatorAccLogin", filter.getOpLogin()))
.and(contain("operatorName", filter.getOpName()))
.and(contain("number", filter.getNumber()))
.and(equal("status", filter.getStatus()))
.and(contain("note", filter.getNote()));
return phoneRepository.findAll(specifications, filter.getPageable());
}
public interface PhoneRepository extends CrudRepository<Phone, Integer>, JpaSpecificationExecutor<Phone> {
class Specifications {
public static Specification<Phone> equal(@NonNull String column, @NotNull Object value) {
return (root, criteriaQuery, criteriaBuilder) -> criteriaBuilder.equal(root.get(column), value);
}
public static Specification<Phone> contain(@NonNull String column, @NotNull String value) {
return (root, criteriaQuery, criteriaBuilder) -> criteriaBuilder.like(root.get(column), value);
}
public static Specification<Phone> isBetween(@NonNull String column, @NonNull Timestamp from, @NonNull Timestamp to) {
return (root, criteriaQuery, criteriaBuilder) -> criteriaBuilder.between(root.get(column), from, to);
}
}
}
Но загвоздка в том, что если в .and(contain("fieldName", value) в качестве значения попадает null, то соответственно запрос требует null в значении соответствующего столбца, для того чтобы считать кортеж подпадающем под условие, а мне необходимо сделать так, чтобы поле просто исключалось из списка условий, если оно равно null.
Конечно в самом крайнем случае можно создать отдельный Specifications для каждого поля и наделать кучу if else но хочется сделать нормально. Подскажите пожалуйста как можно выйти из положения имея в виду что на слудующем шаге мне придется учитывать тот факто что таких репозиториев у меня будет много под каждый вид сущьности, не только Phone и методы static Specification<Phone> equal(...) по сути повторяются.
В общем, буду весьма признателен за любые конструктивные соображения на этот счет.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей