一、新需求和问题
根据前面学习的内容,我们做这样一个简单的查询需求:对user表进行按性别查询并按年龄排序。实现如下:
映射文件配置:
<select id="getUserList" resultType="User">
select * from user where sex=#{sex} order by #{ageCol}
</select>
接口声明和调用示列:
public List getUserList(@param("sex")String sex,@param("ageCol")String column);
List<User> userList = userOperation.getUserList(1,"age");
上面的程序执行看起来没问题,但是实际执行起来并不会对,发现
按要求查询了数据,但是没有进行按要求排序。
二、解决办法
在映射配置文件中进行如下修改:
<select id="getUserList" resultType="User">
select * from user where sex=#{sex} order by ${ageCol}
</select>
修改说明:即将#{ageCol}修改为${ageCol},通过将#修改为$后,执行程序发现满足需要,查出了数据并按要求排序了。
三、解析问题(#{}和${}的区别)
1. #{}将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #{ageCol},如果参数传入的值是字符串“age”,那么解析成sql时的值为order by "age", 如果传入的值是id,则解析成的sql为order by "id".
2. ${}将传入的数据直接显示生成在sql中。如:order by#{ageCol},如果参数传入的值是字符串“age”,那么解析成sql时的值为order by age, 如果传入的值是id,则解析成的sql为order by id.
3. #{}方式能够很大程度防止sql注入。
4.${}方式无法防止Sql注入,存在一定风险。
5.${}方式一般用于传入数据库对象,例如传入表名、列名.
6.一般能用#的就别用$,除非要传入数据库对象.
重要: 默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并以它为背景设置安全的值(比如?)。这样做很安全,很迅速也是首选做法;使用${}接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。