Создание цепочки предикатов для фильтра в стриме
Есть REST сервис. В GET запросе могут присутствовать параметры: обычные на сравнение, дата "от", дата "до". Параметры могут быть в любой комбинации. Параметры даты формируют временной промежуток:
- если нет даты "от" - то отбираются от самой первой (по времени) записи
- если нет "до" - до самой то отбираются до самой последней (по времени) записи
Идея в том, чтобы создать фильтр для любой ситуации и использовать его в stream()
Есть такая реализация:
private Specification<User> byFilter(Map<String, String> requestParams) {
return requestParams
.entrySet()
.stream()
.filter(param -> !param.getKey().equals(TIME_FROM) && !param.getKey().equals(TIME_TO))
.map(entry -> byAttributeValue(entry.getKey(), entry.getValue()))
.reduce(Specification::and).orElse(null);
}
Репозиторий:
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
List<User> findAllByOrderByTimeAsc();
static Specification<User> byAttributeValue(String field, Object value) {
return (user, query, cb) -> cb.equal(user.get(field), value);
}
Set<User> findByTimeBetween(Date startDate, Date endDate);
}
Смысл таков: если есть хоть один параметр по времени, то идет выборка по дате (много кода со связями, не представлено) потом выборка с использованием byFilter(), потом выборки сводятся; если нет - сразу выборка через byFilter().
Работает, но реализация не нравится. Кажется избыточной, не гибкой. Не получается додумать использование Specification, Predicate в stream().
Как в byFilter "прикрутить" фильтр по дате?
Будет здорово, если кто-нибудь даст толковое объяснение принципа работы кода
static Specification<User> byAttributeValue(String field, Object value) {
return (user, query, cb) -> cb.equal(user.get(field), value);
}