商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > MyBatis-Plus中实现自定义复杂排序逻辑

MyBatis-Plus中实现自定义复杂排序逻辑

  发布于2026-07-23 阅读(0)

扫一扫,手机访问

在使用MyBatis-Plus做数据库操作时,经常会遇到一些需要根据复杂条件来排序的场景——不是简单地按某个字段升序或降序,而是多个字段、特定规则,甚至要处理特殊值。下面通过一个实际案例,看看怎么在MyBatis-Plus中实现这种自定义的复杂排序逻辑。

MyBatis-Plus中实现自定义复杂排序逻辑

场景描述

假设有一个车辆保险信息查询功能,要求按gateNo字段排序。这个字段的格式是X-YYY,其中X可以是数字或特殊字符串(比如“天”),YYY是数字。排序规则是:先按X的数值排序,但如果X是“天”,则排在所有数字之后;同时,在X相同的情况下,再按YYY的数值排序。

举个例子:1-0012-001天-0011-002,期望顺序是1-0011-0022-001天-001。纯靠MyBatis-Plus自带的排序方法显然不够用,需要引入自定义SQL片段。

解决方案

MyBatis-Plus的QueryWrapper提供了丰富的查询条件构建方法,但对于这种复杂排序,最直接的方式就是利用last方法追加原生SQL片段。下面分步骤说明。

步骤1:定义QueryWrapper

首先,创建一个QueryWrapper实例。如果查询模型(model)为空,直接返回空实例,避免后续处理报错。

QueryWrapper queryWrapper = new QueryWrapper<>();
if (model == null) {
    return queryWrapper;
}

步骤2:添加自定义排序逻辑

核心排序逻辑用last方法追加到SQL末尾。这里用CASE WHEN处理特殊值“天”,再用CAST配合SUBSTRING_INDEX把字符串拆成数值,确保按数值排序而不是按字符串字典序。

String customOrderSql = "CASE WHEN gate_no LIKE '天-%' THEN 2 ELSE 1 END, " +
    "CAST(SUBSTRING_INDEX(gate_no, '-', 1) AS UNSIGNED), " +
    "CAST(SUBSTRING_INDEX(gate_no, '-', -1) AS UNSIGNED)";
queryWrapper.last("ORDER BY " + customOrderSql);

详细解释

  1. 特殊值处理CASE WHEN gate_no LIKE '天-%' THEN 2 ELSE 1 END,将“天”开头的记录标记为2,其他为1。排序时1在前,2在后,从而把“天”的记录排到最后。
  2. 按X排序SUBSTRING_INDEX(gate_no, '-', 1)提取“-”前面的部分(即X),再用CAST(… AS UNSIGNED)转成无符号整数,确保按数值大小排序,而不是按字符串“1”、“2”、“10”这样的顺序。
  3. 按YYY排序SUBSTRING_INDEX(gate_no, '-', -1)提取“-”后面的部分(即YYY),同样转成数值排序。这样在X相同的情况下,YYY小的排在前面。

步骤3:添加其他查询条件

实际业务中,除了排序,还需要根据多个字段过滤。比如按车辆ID、车牌号等条件筛选。这里只展示几个示例条件,方便理解整体结构:

queryWrapper
    .eq(model.getCarId() != null && model.getCarId() != 0, "car_id", model.getCarId())
    .like(StringUtils.isNotBlank(model.getLicensePlate()), "license_plate", model.getLicensePlate());

完整方法

把以上步骤整合起来,就得到了一个完整的查询包装器构建方法:

@Override
public QueryWrapper onSelectWhere(VCzInsuranceEntity model) {
    QueryWrapper queryWrapper = new QueryWrapper<>();
    if (model == null) {
        return queryWrapper;
    }

    String customOrderSql = "CASE WHEN gate_no LIKE '天-%' THEN 2 ELSE 1 END, " +
        "CAST(SUBSTRING_INDEX(gate_no, '-', 1) AS UNSIGNED), " +
        "CAST(SUBSTRING_INDEX(gate_no, '-', -1) AS UNSIGNED)";
    queryWrapper.last("ORDER BY " + customOrderSql);

    queryWrapper
        .eq(model.getCarId() != null && model.getCarId() != 0, "car_id", model.getCarId())
        .like(StringUtils.isNotBlank(model.getLicensePlate()), "license_plate", model.getLicensePlate());

    return queryWrapper;
}

这种方法的核心思路,就是利用last方法手写原生SQL,把排序逻辑完全掌控在自己手里。虽然看起来多写了几行,但面对类似“特殊值置后、多字段数值排序”这样的需求,它是最清晰、最可靠的方案。

本文转载于:https://www.jb51.net/program/367876946.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注