Querydsl JPQLQuery如何不生成列表直接获取查询结果记录数
QueryDSL 3.7.4 分组查询直接获取总数方案
针对带group by的查询需要统计总记录数的场景,不需要先拉取全量结果列表再算size,可通过以下两种方式实现:
方案1:使用listResults方法直接获取总计数
QueryDSL 3.x内置了listResults()方法,会自动生成count统计查询,不需要拉取业务数据,直接返回总记录数:
Expression[] groupByExpression = // 获取group by表达式 Predicate whereCondition = // 获取查询条件谓词 long count = query.from(myEntityName) .where(whereCondition) .groupBy(groupByExpression) .listResults(constructorExpression) .getTotal();
该方案兼容性最高,不需要修改原有查询的分组、条件逻辑,直接替换原有list().size()即可生效。
方案2:构造distinct分组键的count查询(性能最优)
分组后的总记录数等价于分组字段组合的去重计数,直接构造计数查询即可:
Expression[] groupByExpression = // 获取group by表达式 Predicate whereCondition = // 获取查询条件谓词 // 多字段分组时用tuple封装分组键 Expression<?> groupKey = groupByExpression.length == 1 ? groupByExpression[0] : Projections.tuple(groupByExpression); long count = query.from(myEntityName) .where(whereCondition) .singleResult(JPAExpressions.select(groupKey).distinct().count());
该方案没有多余的投影解析逻辑,性能略优于方案1,适合对性能要求极高的场景。
注意事项
- 两种方案都只会执行count统计查询,不会加载全量分组数据,大数据量下性能比原有实现提升非常明显
- 不建议直接使用JPAQuery原生的
count()方法,该方法在带group by的查询中会返回每个分组的单独计数,无法拿到总组数
内容的提问来源于stack exchange,提问作者Joel George
相关产品推荐
相关产品推荐

