写点什么

一个 ${}引发的惨案

  • 2022 年 5 月 14 日
  • 本文字数:680 字

    阅读完需:约 2 分钟

#{} 和 {}最大的区别在于:预编译处理方式不一样,#{} 在预处理时,会把参数部分用一个占位符 ? 代替,而{}在预处理会直接把参数和原本 SQL 拼接到一起。


预编译结束之后,MyBatis 会执行动态解析,解析 SQL 并发送给 MySQL 执行,这个时候对于 ${}而言,此时的 SQL 就是一条完整可执行的 SQL,而对 #{} 而言,此时的 SQL 是带有?占位符的 SQL,MySQL 会进行进一步的处理。


这也就是为什么我们都推荐使用 #{} ,尽量少使用 {}的原因,因为#{}可以解决SQL注入的问题,{}不行。


四、实例讲解


在下面的查询语句中,如果 orderId 的值为 202011081153,则两种方式无任何区别:


select * from order where orderId = #{orderId};


select * from order where orderId = ${orderId};


其解析之后的结果均为


select * from order where orderId = 202011081153;


但是 #{} 和 ${} 在预编译中的处理是不一样的。


#{} 在预处理时,会把参数部分用一个占位符 ? 代替,变成如下的 SQL 语句:


select * from order where orderId = ?;


而 ${} 则只是简单的字符串替换,在动态解析阶段,该 SQL 语句会被解析成


select * from order where orderId = 202011081153;


以上,#{} 的参数替换是发生在 DBMS 中,而 ${} 则发生在动态解析过程中。


那么,在使用过程中我们应该使用哪种方式呢?



答案是:优先使用 #{}。因为 ${} 会导致 SQL 注入的问题。


再看下面的例子:


select * from ${tableName} 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 where name = #{name}


在这个例子中,如果表名为


order; delete order; --


则动态解析之后 SQL 如下:

用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
一个${}引发的惨案_Java_爱好编程进阶_InfoQ写作社区