这篇文章主要为大家展示了“mybatis中#{}和${}有哪些区别”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“mybatis中#{}和${}有哪些区别”这篇文章吧。数据库数据:dao接口:Mapper.xml:执行测试代码:查看执行结果:发现都能够查询出来${}会产生SQL注入,#{}不会产生SQL注入问题我们做一个测试:查询生成的SQL语句:我们传递的参数是aaa' or 1=1 --
,导致查询出来了全部的数据。大家可以想象一下,如果我是要根据id删除呢?如果我传递的是:1' or 1=1; --
,结果会是什么样,我想大家应该已经知道了。我这里id是Integer类型,不好测试,就不带大家测试了,大家有兴趣可以自己私下测试。如果上面使用的是#{}就不会出现SQL注入的问题了#{}
匹配的是一个占位符,相当于JDBC中的一个?
,会对一些敏感的字符进行过滤,编译过后会对传递的值加上双引号,因此可以防止SQL注入问题。${}
匹配的是真实传递的值,传递过后,会与sql语句进行字符串拼接。${}
会与其他sql进行字符串拼接,不能预防sql注入问题。查看#{}
和${}
生成的SQL语句:String abc=“123”;#{abc}=”123″${value}=123;网上关于这类问题非常多,总结出来就两个原因:1)#{}
底层采用的是PreparedStatement,会预编译,因此不会产生SQL注入问题;其实预编译是MySQL自己本身的功能,和PreparedStatement没关系;而且预编译也不是咱们理解的那个预编译,再者PreparedStatement底层默认根本没有用到预编译(要我们手动开启)!详细往下看2)#{}
不会产生字符串拼接,${}
会产生字符串拼接,因此${}
会出现SQL注入问题;这两个答案都经不起深究,最终答案也只是停留在表面,也没人知道具体是为什么。我们翻开MySQL驱动的源码一看究竟;打开PreparedStatement
类的setString()
方法(MyBatis在#{}
传递参数时,是借助setString()
方法来完成,${}
则不是):setString()方法全部源码:我们执行#{}的查询语句,打断点观察:最终传递的参数如下:最终传递的参数为:'aaa' or 1=1 --
咱们在数据库中执行如下SQL语句(肯定是查询不到数据的):如果把PreparedStatement
加的那根"/"
去掉呢?我们执行SQL试试:我们也可以通过MySQL的日志来观察#{}和${}产生的SQL语句来分析问题:1)开启MySQL日志:在MySQL配置文件中的[mysqld]下增加如下配置:2)重启MySQL服务(要以管理员身份运行):使用mybatis分别执行如下两条SQL语句:查看MySQL日志:既然#{}
比${}
好那么多,那为什么还要有${}
这个东西存在呢?干脆都用#{}
不就万事大吉吗?其实不是的,${}
也有用武之地,我们都知道${}
会产生字符串拼接,来生成一个新的字符串例如现在要进行模糊查询,查询user表中姓张的所有员工的信息sql语句为:select * from user where name like '张%'
此时如果传入的参数是 “张”如果使用${}
:select免费云主机域名 * from user where name like '${value}%'
生成的sql语句:select * from user where name like '张%'
如果使用#{}
:select * from user where name like #{value}"%"
生成的sql语句:select * from user where name like '张'"%"
如果传入的参数是 “张%”使用#{}:select * from user where name like #{value}
生成的sql语句:select * from user where name like '张%'
使用${}
:select * from user where name like '${value}'
生成的sql语句:select * from user where name like '张%'
通过上面的SQL语句我们能够发现#{}
是会加上双引号,而${}
匹配的是真实的值。还有一点就是如果使用${}
的话,里面必须要填value,即:${value}
,#{}
则随意场景举例:代码测试:执行之后,发现执行成功我们可以切换一下,把${}改成#{},会出现SQL语法错误的异常MyBatis的#{}
之所以能够预防SQL注入是因为底层使用了PreparedStatement
类的setString()
方法来设置参数,此方法会获取传递进来的参数的每个字符,然后进行循环对比,如果发现有敏感字符(如:单引号、双引号等),则会在前面加上一个'/'
代表转义此符号,让其变为一个普通的字符串,不参与SQL语句的生成,达到防止SQL注入的效果。其次${}
本身设计的初衷就是为了参与SQL语句的语法生成,自然而然会导致SQL注入的问题(不会考虑字符过滤问题)。1)#{}
在使用时,会根据传递进来的值来选择是否加上双引号,因此我们传递参数的时候一般都是直接传递,不用加双引号,${}
则不会,我们需要手动加2)在传递一个参数时,我们说了#{}
中可以写任意的值,${}
则必须使用value;即:${value}
3)#{}
针对SQL注入进行了字符过滤,${}
则只是作为普通传值,并没有考虑到这些问题4)#{}
的应用场景是为给SQL语句的where字句传递条件值,${}
的应用场景是为了传递一些需要参与SQL语句语法生成的值。以上是“mybatis中#{}和${}有哪些区别”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注百云主机行业资讯频道!
小编给大家分享一下CSS如何设置行间距,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! 首先我们应该知道在css中并没有直接可以设置行间距的属性,所以我们就需要借助行高line-h…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。