Spring JpaRepository findBy... В (Collection) возвращает соединение не пересечение

134
20

У меня есть метод запроса в моем JpaRepository

    Page<Course> findDistinctCourseByAttrsInAllIgnoreCase(Set<String> a, Pageable page);

для поиска объектов Course по их переменной экземпляра Set<String> attrs. Учитывая набор с "Foo" и "баром", я хочу, чтобы найти a Course, чей attrs содержит как "Foo" и "бар", т.е. пересечение Course с "Foo" и теми, кто с "баром". Этот метод выше возвращает объединение.

Есть ли способ сделать это с помощью запросов JpaRepository или мне нужно сделать несколько вызовов и найти пересечение самостоятельно?

спросил(а) 2017-11-28T12:03:00+03:00 3 года, 6 месяцев назад
1
Решение
99

Что-то вроде этого должно сделать это:

@Query("SELECT c FROM Course c JOIN Attribute a WHERE LOWER(a.name) IN (:attributes) GROUP BY c HAVING COUNT(c) = :size")
public Page<Course> findByAllAttributes(@Param("attributes") Set<String> attributes, @Param("size") Integer size, Pageable page);

и вы называете это следующим образом:

Page<Course> page = findByAllAttributes(set.stream()
.map(String::toLowerCase)
.collect(Collectors.toSet(),
set.size(), page);

ответил(а) 2017-11-28T17:16:00+03:00 3 года, 6 месяцев назад
63

В маловероятном случае, если вы знаете количество фронта вы могли бы объединить несколько ограничений с a And:

...AttrsInAndAttrsIn...

Но даже если это предположение будет очень уродливым.

Таким образом, следующий лучший вариант - это, вероятно, спецификация и factoryMethod, строящая спецификацию из Set<String> или из varargs.

Вашему хранилищу необходимо расширить JpaSpecificationExecutor. Вы бы назвали это так

Page<Course> findAll(matchesAll(attrs), pageable) 

И фабричный метод будет выглядеть примерно так:

Specification<Course> matchesAll(Set<String> attrs) {
return (Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> {
// construct Predicate by combining calls to builder.isMember
// https://docs.oracle.com/javaee/6/api/javax/persistence/criteria/CriteriaBuilder.html#isMember(E,%20javax.persistence.criteria.Expression)

}
}

ответил(а) 2017-11-28T14:25:00+03:00 3 года, 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема