龙骋唧 发表于 2025-7-9 22:03:15

QueryDsl动态排序的实现

写在前面,最近项目持久层框架需要使用JPA+QueryDsl,而网上相关的资料特别少。我将在JPA和QueryDsl标签下记录学习过程中遇到的问题和解决方案,希望能帮到有需要的小伙伴。
本文介绍使用QueryDsl实现动态排序的方法,即前端动态地向后端传递排序字段和排序规则,后端返回相应的结果。
步骤一

在项目的util包下创建一个QueryDslSortUtil工具类,直接复制粘贴以下代码即可。
public class QueryDslSortUtil {
    /**
   * 将字段名和排序方向转换成 QueryDSL 的 OrderSpecifier
   *
   * @param sortField 排序字段名
   * @param sortOrder 排序方向 (asc或desc)
   * @param pathBaseQ类对象(例如QArticle.article)
   * @return OrderSpecifier
   */
    public static <T> OrderSpecifier<?> buildSort(String sortField, String sortOrder, EntityPathBase<T> pathBase) {
      Order order = "asc".equalsIgnoreCase(sortOrder) ? Order.ASC : Order.DESC;
      Path<T> path = Expressions.path(pathBase.getType(), pathBase, sortField);
      return new OrderSpecifier(order, path);
    }
}步骤二

在Repository中调用QueryDslSortUtil工具类的buildSort方法,到这里就可以正常使用了。示例代码如下。
@Component
public class ArticleAdvancedRepositoryImpl implements ArticleAdvancedRepository {
    @Resource
    private JPAQueryFactory jpaQueryFactory;

    @Override
    public Page dynamicFindAll(int page, int size, ArticleQueryVO articleQueryVO) {
      Pageable pageable = PageUtil.handlePage(page, size); //分页对象
      QArticle qArticle = QArticle.article; //这里以Article实体为例,请根据实际情况进行修改

      //构建动态排序
      OrderSpecifier<?> orderSpecifier = QueryDslSortUtil.buildSort(
                articleQueryVO.getSortField().name(), //前端传来的排序字段
                articleQueryVO.getSortOrder().name(), //前端传来的排序规则(升序/降序)
                qArticle //Article实体对应的Q类对象
      );

      //主查询
      List results = jpaQueryFactory.select(...) //省略了投影的字段,请根据实际需要编写
                .from(qArticle)
                .orderBy(orderSpecifier)
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();

      //以下代码逻辑省略
      //...

      //计算总行数
      Long totalCount = Optional.ofNullable(jpaQueryFactory.select(qArticle.count())
                .from(qArticle)
                .fetchOne()).orElse(0L);
      return new PageImpl<>(results, pageable, totalCount);
    }
}补充

QueryDSL提供了严格的类型检查。return new OrderSpecifier(order, path);会出现警告,但不影响使用。
如果希望完全消除警告,可以将步骤一的buildSort方法替换成以下代码:
   public static <T extends Comparable<? super T>> OrderSpecifier<?> buildSort(String sortField, String sortOrder, EntityPathBase<T> pathBase) {
       Order order = "asc".equalsIgnoreCase(sortOrder) ? Order.ASC : Order.DESC;
       Path<T> path =Expressions.path(pathBase.getType(), pathBase, sortField);
       return new OrderSpecifier<>(order, path);
   }重要: 如果使用上述修改后的buildSort方法,实体类必须要实现Comparable接口,否则无法通过编译。
public class Article implements Comparable{
    //...实体类的属性

    @Override
    public int compareTo(Article o) {
      //...实现比较的逻辑
      return 0;
    }
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: QueryDsl动态排序的实现