MyBatis动态排序陷阱解析:从原理到实战的深度避坑指南
当你满怀信心地在MyBatis中实现了一个动态排序功能,测试时却发现数据依然杂乱无章——这种场景恐怕不少Java开发者都遇到过。动态排序作为数据展示的刚需功能,其实现过程中隐藏着MyBatis参数处理的深层机制,而盲目使用#{}和${}符号就像在代码里埋下了不定时炸弹。
1. 问题现象与初步诊断
上周在重构一个老项目时,我遇到了一个典型的动态排序失效案例。前端传入的排序字段和方向参数明明正确,但返回的数据始终按默认主键排序。查看日志发现SQL语句看似正常:
SELECT * FROM products WHERE category_id = ? ORDER BY ? ?
参数绑定显示为:
Parameters: 5(Integer), "price"(String), "DESC"(String)
但实际执行结果却完全没有按价格降序排列。这种"假成功"现象特别具有迷惑性——SQL语法正确执行,但业务效果不符合预期。
常见错误表象:
- 日志显示排序参数已正确传入
- 无任何SQL异常抛出
- 返回数据保持无序或默认排序状态
- 直接在数据库客户端执行生成的SQL同样无效
2. 核心问题解析:#{}与${}的本质区别
要彻底理解这个问题,需要深入MyBatis的参数处理机制。这两种占位符在预编译阶段有着完全不同的处理方式:
| 特性 | #{} 预编译占位符 | ${} 字符串替换 |
|---|---|---|
| 处理阶段 | SQL预编译阶段 | SQL解析阶段 |
| 安全性 | 防SQL注入 | 有注入风险 |
| 参数类型 | 自动类型转换 | 直接文本替换 |
| 适用场景 | WHERE条件值 | 表名/字段名等SQL关键字 |
| 输出效果 | 生成带引号的参数值 | 原始文本插入 |
当我们在ORDER BY子句中使用#{}时:
ORDER BY #{fieldName} #{sortDirection}
实际生成的SQL会是:
ORDER BY 'p


1912

被折叠的 条评论
为什么被折叠?



