首页 > 编程语言 >MyBatis-Plus自定义复杂排序逻辑实现

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

来源:互联网 2026-07-24 08:27:08

在MyBatis-Plus中,通过QueryWrapper的last方法追加原生SQL片段,可实现复杂排序。例如处理gate_no字段时,使用CASEWHEN将特殊值“天”置后,再提取其中的X和YYY部分并转为数值排序,从而满足多字段组合及特殊规则的自定义需求,有效提高排序灵活性。

在使用 MyBatis-Plus 进行数据库操作时,常会遇到需要根据复杂条件排序的场景——并非简单的单字段升序或降序,而是涉及多字段、特定规则甚至特殊值处理。下面通过一个实际案例,介绍如何在 MyBatis-Plus 中实现自定义复杂排序逻辑。

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

长期稳定更新的攒劲资源: >>>点此立即查看<<<

场景描述

假设有一个车辆保险信息查询功能,要求按 gate_no 字段排序。该字段格式为 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,将排序逻辑完全掌控在自己手中。虽然多写了几行代码,但面对“特殊值置后、多字段数值排序”这类需求,它是最清晰、最可靠的方案。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。