温馨提示×

温馨提示×

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

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

动态SQL有哪些常见坑

发布时间:2026-10-20 00:40:39 来源:亿速云 阅读:93 作者:小樊 栏目:数据库

动态 SQL(最常见于 MyBatis、Spring JDBC、或者后台自己拼 SQL)确实很灵活,但也非常容易踩坑。下面按常见坑点 + 原因 + 建议来总结,偏实战向。


一、SQL 注入(最常见、最危险)

坑点

直接拼接用户输入:

String sql = "select * from user where name = '" + name + "'";

原因

用户输入 ' or '1'='1 就能改变语义。

建议

  • 永远用 占位符 / 参数绑定
  • MyBatis 用 #{} 而不是 ${}
  • 禁止把用户输入直接拼进 SQL

二、误用 ${}(MyBatis 重灾区)

坑点

order by ${column}

看起来“动态”,其实是字符串替换,不是参数。

风险

  • SQL 注入
  • 类型不匹配
  • 排序字段不可控

建议

  • 排序/表名必须用白名单
if (!allowedColumns.contains(column)) {
    throw new IllegalArgumentException();
}

三、条件拼接导致 SQL 语法错误

坑点

select * from user
where
<if test="name != null">
  and name = #{name}
</if>

如果前面没有条件,就会变成:

where and name = ?

建议

  • 用 <where> 标签
  • 或者统一加 1=1
<where>
  <if test="name != null">
    and name = #{name}
  </if>
</where>

四、动态 IN 条件处理不当

坑点

where id in (#{ids})

传 "1,2,3" 会失败。

建议

  • 用 <foreach>
where id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
  #{id}
</foreach>

五、空集合 / null 导致 SQL 异常

坑点

<if test="list != null and list.size > 0">

忘了判断 size,直接拼 in () → SQL 报错。

建议

  • 明确判空
  • 业务层提前 return
  • 或用默认条件兜底

六、类型隐式转换导致索引失效

坑点

where phone = #{phone}

phone 是 varchar,但传了数字。

结果

  • 索引失效
  • 全表扫描

建议

  • 类型严格一致
  • 数据库字段和 Java 类型对齐

七、动态 SQL 太复杂,难以维护

坑点

一个 SQL 里十几个 <if>,逻辑比代码还复杂。

风险

  • 改一处崩一片
  • 测试极难覆盖

建议

  • 拆 SQL
  • 用 Query Object / Specification
  • 简单条件走代码拼装

八、分页与动态条件冲突

坑点

  • count SQL 和 list SQL 不一致
  • 动态条件只加在 list,没加在 count

建议

  • 共用同一套条件构造器
  • 分页插件统一管理

九、性能问题(生成 SQL 不可控)

坑点

  • 动态生成超长 SQL
  • 条件组合爆炸
  • 无法命中已有执行计划

建议

  • 限制组合数量
  • 热点查询单独写死 SQL
  • 加监控和慢查询日志

十、测试覆盖不足

坑点

只测了“有参数”,没测:

  • 全空
  • 半空
  • 极端组合

建议

  • 参数矩阵测试
  • SQL 打印 + 单测校验

一句话总结

动态 SQL 的核心坑:注入、语法、索引、可维护性。
原则:能参数化就参数化,能简单就别动态,动态必须可控。

如果你用的是 MyBatis / MyBatis-Plus / JPA / 原生 JDBC,我可以针对具体技术给更细的“避坑模板”。

向AI问一下细节

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

AI
助
手