可以在Spring Data Jpa Specification中添加count(*)和groupBy吗?

我正在使用Spring Boot和Spring Data Jpa编写应用程序。

我有一个使用RSQL(我使用this库)和Specification的方法来对数据库的where子句进行过滤器调用。

我的存储库:

public interface BaseRepository<M extends BaseModel> extends JpaRepository<M,Long>,JpaSpecificationExecutor<M>{

}

在服务中,我调用存储库:

String filter = "createdDate > 2019-09-04T11:52:59.449";
return repository.findAll(toSpecification(filter),pageable).getcontent();  

因此,我使用上面的库来生成一个Specification并将其传递到存储库中。

现在,我需要按一些字段对结果进行分组。

问题是如何在规范中添加 count groupBy ?或者,也许我需要创建一个谓词,在其中定义此 count groupBy (以某种方式)并以此为基础进行规范?有什么更好的方法呢?

更新#0

我已经设法在结果sql查询中按组添加了一个组。我创建了一个新的规范对象,在该对象中,我按参数定义了所有分组,然后将此规范与原始规范组合在一起。

String filter = "createdDate > 2019-09-04T11:52:59.449";

Specification<M> groupBySpec = new Specification<M>() {

            @Override
            public Predicate toPredicate(Root<M> root,CriteriaQuery<?> query,CriteriaBuilder criteriaBuilder) {

                List<Expression<?>> groupByParams = new ArrayList<>();

                groupByParams.add(root.get("param1"));
                groupByParams.add(root.get("param2"));

                query.groupBy(groupByParams);

                return query.getGroupRestriction();
            }
        };


return repository.findAll(groupBySpec.and(toSpecification(filter)),pageable).getcontent();     

问题是它总是选择所有列,但我只需要按组选择那些列。

结果是我得到一个SQL异常:ERROR: column "columnName" must appear in the GROUP BY clause or be used in an aggregate function

我已经尝试过使用criteriaQuery.multiselect(root.get("column1"),root.get("column2")).distinct(true).getGroupRestriction();这样的多选功能,但是无论如何它都会选择所有列。

如果我使用@Query("query")(在其中定义要选择的列,但需要使用Criteria Api / Specification来工作),它将起作用。

mystiquec 回答:可以在Spring Data Jpa Specification中添加count(*)和groupBy吗?

您可以创建自己的GroupBySpecification类,该类将groupBy表达式添加到其他规范:

public class GroupBySpecification implements Specification {
  Specification original;
  Parameters parameters; // whatever data needed for calculating groupBy expression

  public GroupBySpecification(Specification original,Parameters parameters){
      this.original = original;
      this.parameters = parameters;
  }
  public Predicate toPredicate(Root<T> root,CriteriaQuery<?> query,CriteriaBuilder criteriaBuilder) {

      Expression<?> expression = ...; // whatever logic needed to be used on parameters...
      criteriaBuilder.groupBy(expression);
      return original.toPredicate(root,query,criteriabuilder);
  }

}

然后您可以像这样使用它:

String filter = "createdDate > 2019-09-04T11:52:59.449";
return repository.findAll(new GroupBySpecification(toSpecification(filter),parameters),pageable).getContent();  

如果您需要 count ,请调用适当的存储库方法:

repository.count(new GroupBySpecification(toSpecification(filter),parameters));  
本文链接:https://www.f2er.com/3159759.html

大家都在问