Mysql Spring JpaRepository由…在(集合)中查找返回并集而不是交集

Mysql Spring JpaRepository由…在(集合)中查找返回并集而不是交集,mysql,spring,hibernate,spring-data-jpa,spring-repositories,Mysql,Spring,Hibernate,Spring Data Jpa,Spring Repositories,我在我的JpaRepository中有一个查询方法 Page<Course> findDistinctCourseByAttrsInAllIgnoreCase(Set<String> a, Pageable page); 通过实例变量集attrs查找课程对象。给定一个带有foo和bar的集合a,我想找到属性同时包含foo和bar的课程,即带有foo的课程和带有bar的课程的交叉点。上面的这个方法返回一个联合。 JPA正向查询是否有办法做到这一点,或者我是否需要多

我在我的JpaRepository中有一个查询方法

    Page<Course> findDistinctCourseByAttrsInAllIgnoreCase(Set<String> a, Pageable page);
通过实例变量集attrs查找课程对象。给定一个带有foo和bar的集合a,我想找到属性同时包含foo和bar的课程,即带有foo的课程和带有bar的课程的交叉点。上面的这个方法返回一个联合。
JPA正向查询是否有办法做到这一点,或者我是否需要多次调用并自己找到交叉点?

在不太可能的情况下,您事先知道as的数量,您可以将多个约束与和结合起来:

但即使前提条件成立,这也将非常丑陋

因此,下一个最好的选择可能是一个规范和一个从集合或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)

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

像这样的东西应该可以:

@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);
你这样称呼它:

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)

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