Spring JpaRepository findBy...In(Collection) returns 并集不是交集

Spring JpaRepository findBy...In(Collection) returns union not intersection

我的 JpaRepository 中有一个查询方法

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

通过实例变量 Set<String> attrs 查找 Course 个对象。给定一个包含 "foo" 和 "bar" 的集合 a,我想找到 Courseattrs 包含两个 "foo" "bar",即 Course 与 "foo" 和 "bar" 的交集。这个方法上面returns一个union。

有没有办法使用 JpaRepository 查询来执行此操作,还是我必须进行多次调用并自己找到交集?

在不太可能的情况下,您知道前面 a 的数量,您可以将多个约束与 And:

结合使用
...AttrsInAndAttrsIn...

但即使前提条件成立,那也很难看。

因此,下一个最佳选择可能是一个规范和一个从 Set<String> 或可变参数构建规范的工厂方法。

您的存储库需要扩展 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)

    }
}

像这样的东西应该可以做到:

@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);