温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

动态SQL如何实现排序

发布时间:2026-09-08 21:02:07 来源:亿速云 阅读:90 作者:小樊 栏目:数据库

动态 SQL(MyBatis、JDBC、Spring Data 等场景都常见)中,“排序”通常是不能简单用 ? 占位符的,因为 ORDER BY 后面跟的是列名和方向,属于 SQL 结构,而不是参数。

下面以最常见的 MyBatis 为例,讲几种正确实现方式。


一、最常见方式:使用 ${}(必须白名单校验)

<select id="list" resultType="User">
  SELECT * FROM user
  ORDER BY ${sortField} ${sortOrder}
</select>

调用:

map.put("sortField", "create_time");
map.put("sortOrder", "DESC");

✅ 优点:简单直观
❌ 风险:${} 会直接拼接 SQL,容易被注入

✅ 安全写法(推荐)

private static final Set<String> ALLOW_FIELDS =
    Set.of("id", "name", "create_time");

private static final Set<String> ALLOW_ORDERS =
    Set.of("ASC", "DESC");

if (!ALLOW_FIELDS.contains(sortField)) {
    sortField = "id";
}
if (!ALLOW_ORDERS.contains(sortOrder)) {
    sortOrder = "ASC";
}

二、使用 <choose> 标签(最安全)

<select id="list" resultType="User">
  SELECT * FROM user
  ORDER BY
  <choose>
    <when test="sortField == 'name'">name</when>
    <when test="sortField == 'age'">age</when>
    <otherwise>id</otherwise>
  </choose>
  <choose>
    <when test="sortOrder == 'DESC'">DESC</when>
    <otherwise>ASC</otherwise>
  </choose>
</select>

✅ 完全防止 SQL 注入
✅ 适合字段较少的情况


三、多字段排序(动态)

<select id="list" resultType="User">
  SELECT * FROM user
  <where>
    <if test="status != null">AND status = #{status}</if>
  </where>
  ORDER BY
  <foreach collection="sortList" item="s" separator=",">
    ${s.field} ${s.order}
  </foreach>
</select>

Java:

List<Map<String,String>> sortList = List.of(
    Map.of("field","create_time","order","DESC"),
    Map.of("field","id","order","ASC")
);

⚠️ 同样需要白名单校验


四、MyBatis-Plus 方式(最推荐)

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("create_time");
wrapper.orderByAsc("id");

或前端传参:

wrapper.orderBy(
    true,
    "DESC".equals(order),
    sortField
);

✅ 自动防注入
✅ 代码清晰


五、总结建议

场景 推荐方式
字段少 <choose>
字段多 ${} + 白名单
MyBatis-Plus QueryWrapper
绝对安全 不拼 SQL,用枚举

如果你用的是 MyBatis / JPA / JDBC / 原生 SQL,可以告诉我,我可以给你对应示例。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI