【发布时间】:2020-03-01 19:34:53
【问题描述】:
我正在使用 Spring Boot 和 Spring Data Jpa 编写应用程序。
我有一个使用 RSQL(我使用 this 库)和规范的方法,通过 where 子句对 db 进行过滤器调用。
我的仓库:
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();
所以我使用上面的库来生成规范并将其传递给存储库。
现在我需要按某些字段对结果进行分组。
如何在规范中添加 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 才能工作。
【问题讨论】:
-
你的分组依据是什么,你能给我们一个你正在查询的类的 sn-p。
-
@locus2k 应该可以按从请求 http 参数中获取的不同字段进行分组(例如 orderBy = field1, field2, field3)。这实际上就是过滤器的工作原理(我有一个 http param filter = field1, field2.... 我解析),它用于为 sql 查询创建 where 子句(问题中的静态字符串仅用于示例)。而且我要查询的类非常简单:它只包含一些字段,并且与其他模型没有任何关系。
-
我问是因为看起来 RSQL 仅适用于
WHERE子句进行过滤,而不适用于分组。 Spring 可以做到groupBy,但你必须为它编写查询,这需要知道要查询的字段 -
@locus2k 是的,我知道 RSQL 仅适用于
WHERE。问题是如何将 group by 添加到库已经生成的结果规范中。你到底在说什么类型的查询? -
我现在明白了。可以查看spring.io/blog/2011/04/26/…,看看它是否提供了如何做你想做的事。
标签: java hibernate spring-data-jpa spring-data spring-data-rest