Mybatis中#{}和${}

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注入攻击。

相关推荐