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

假设有一个车辆保险信息查询功能,要求按gateNo字段排序。这个字段的格式是X-YYY,其中X可以是数字或特殊字符串(比如“天”),YYY是数字。排序规则是:先按X的数值排序,但如果X是“天”,则排在所有数字之后;同时,在X相同的情况下,再按YYY的数值排序。
举个例子:1-001、2-001、天-001、1-002,期望顺序是1-001、1-002、2-001、天-001。纯靠MyBatis-Plus自带的排序方法显然不够用,需要引入自定义SQL片段。
MyBatis-Plus的QueryWrapper提供了丰富的查询条件构建方法,但对于这种复杂排序,最直接的方式就是利用last方法追加原生SQL片段。下面分步骤说明。
首先,创建一个QueryWrapper实例。如果查询模型(model)为空,直接返回空实例,避免后续处理报错。
QueryWrapperqueryWrapper = new QueryWrapper<>(); if (model == null) { return queryWrapper; }
核心排序逻辑用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);
CASE WHEN gate_no LIKE '天-%' THEN 2 ELSE 1 END,将“天”开头的记录标记为2,其他为1。排序时1在前,2在后,从而把“天”的记录排到最后。SUBSTRING_INDEX(gate_no, '-', 1)提取“-”前面的部分(即X),再用CAST(… AS UNSIGNED)转成无符号整数,确保按数值大小排序,而不是按字符串“1”、“2”、“10”这样的顺序。SUBSTRING_INDEX(gate_no, '-', -1)提取“-”后面的部分(即YYY),同样转成数值排序。这样在X相同的情况下,YYY小的排在前面。实际业务中,除了排序,还需要根据多个字段过滤。比如按车辆ID、车牌号等条件筛选。这里只展示几个示例条件,方便理解整体结构:
queryWrapper
.eq(model.getCarId() != null && model.getCarId() != 0, "car_id", model.getCarId())
.like(StringUtils.isNotBlank(model.getLicensePlate()), "license_plate", model.getLicensePlate());
把以上步骤整合起来,就得到了一个完整的查询包装器构建方法:
@Override public QueryWrapperonSelectWhere(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,把排序逻辑完全掌控在自己手里。虽然看起来多写了几行,但面对类似“特殊值置后、多字段数值排序”这样的需求,它是最清晰、最可靠的方案。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8