flydoging 2020-06-11
1、#{}将传入的数据都当成一个字符串,会对自动传入的数据加一个引号(单引号?双引号?加了引号就对了)如:
//传入的值是sexorder by #{column}
解析后为
order by “sex” //将会出错
2、${}将传入的数据直接显示生成在sql中,如:
//传入的值是sex order by ${column}
解析后为
order by sex //正确的
3、#{}可以在很大程度上防止sql注入,${}无法防止sql注入
4、${}一般用于传入数据库对象,例如传入表名(mybatis动态查询)
6、能用#就别用$
#使用了PreparedStatement来进行预处理,然后用set的方式对占位符进行设置;
$则是通过Statement直接进行查询,当有参数时直接进行拼接进行查询。(具体大家可以去看jdbc里面的PreparedStatement和Statement的处理方式不同)
mybatis在对SQL语句进行预编译之前,会对SQL进行动态解析,#{}和${}会有不同的变现。
在下面的语句中,name值为zhangsan,下面两种方式得到的结果没有区别
1、select * from user where name = #{name}; 2、select * from user where name = ${name};
得到的解析后的结果均为
select * from user where name = ‘zhangsan‘
但是#{}在动态解析的时候,会把参数部分解析成一个占位符?代替
select * from user where name = #{name}; 动态解析为 select * from user where name = ?;
而${}则是简单的字符替换,在动态解析阶段,该sql会被解析成
select * from user where name = ‘zhangsan‘;
以上,#{} 的参数替换是发生在 DBMS(数据库管理系统) 中,而 ${} 则发生在动态解析过程中。
针对上面的sql,如果传入的值是;drop table user;,
那么第一条用#{}的sql解析为:
select * from user where name = “;drop table user;” //查不到东西
那么第二条用${}的sql解析为:
select * from user where name = ;drop table user;//会出错传入的应该name = lhh;drop table user;才对啊,要是name=;本来就会有错;
这时候已经sql注入了。
优先使用 #{}。因为 ${} 会导致 sql 注入的问题。
若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。