Spring JpaRepository findBy ... In(Collection)返回union而不是交集

时间:2017-11-28 09:03:59

标签: mysql spring hibernate spring-data-jpa spring-repositories

我的JpaRepository中有一个查询方法

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

通过实例变量Course查找Set<String> attrs个对象。给定a设置&#34; foo&#34;和&#34; bar&#34;,我想找到Course其中attrs包含两个&#34; foo&#34; &#34; bar&#34;,即Course s与&#34; foo&#34;的交集以及那些&#34; bar&#34;。上面的方法返回一个union。

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

2 个答案:

答案 0 :(得分:1)

如果您事先知道a的数量,则可以将多个约束与And结合使用:

...AttrsInAndAttrsIn...

但即使先决条件存在,也会非常难看。

所以下一个最佳选项可能是规范和一个从Set<String>或从varargs构建规范的factoryMethod。

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

    }
}

答案 1 :(得分:0)

这样的事情应该成功:

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