Дизайн репозитория на Spring Data JPA

208
21 апреля 2018, 20:13

В задаче по реализации фильтра, столкнулся с следующей проблемой. У фильтра есть некоторое колличество полей, которые в случае если пользователь оставил их пустыми, на сервер, в объект фильтра, прилетают как 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(...) по сути повторяются.

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

READ ALSO
Как эффективно группировать строки?

Как эффективно группировать строки?

Нужное решить такую задачу:

197
Идентификатор группы сообщества

Идентификатор группы сообщества

Хочу сделать Longpoll запрос на сервер vk для бота, но сперва нужно получить ключ и адрес сервера, https://vkcom/dev/groups

201
как Выполнить последовательно

как Выполнить последовательно

Как выполнить последовательно эти два метода? получается что они выполняются одновременно, а нужно чтобы сначала прямоугольник перемещался...

191
SecurityException: Invalid certificates

SecurityException: Invalid certificates

Взял лаунчер из этого репозитория: Launcher Minecraft

203