Mybatis的mapper.xml中有两种方式可以对方法形参取值,#{}和${},这两个的区别用和应用场景有些区别。

本文简述区别

#{ }

#{ }解析SQL脚本时,会使用PreparedStatement执行SQL语句,会将#{}作为占位符?,然后将形参取出赋值,可以有效防止SQL注入

ps:

1
2
3
4
5
<select id="one" resultType="com.example.pojo.Dept">
select *
from dept
where dept_id = #{id};
</select>

image-20200927132936679

1
2
# 最后?占位符会加上引号
select * from dept where dept_id = '1';

${ }

${ }解析SQL脚本时,会直接将形参变量取出,然后拼接在SQL语句中,这里用的也是PreparedStatement

ps:

1
2
3
4
5
<select id="one" resultType="com.example.pojo.Dept">
select *
from dept
where dept_id = ${id};
</select>

image-20200927134308662

这时候就会存在一个问题,SQL注入,传入参数为'' or 1=1 类似恒等式

image-20200927135356876

1
2
select * from dept where dept_id = '' or 1=1;
# 此时会查询出所有数据,同时对数据库也会造成压力

在只有一个形参时{ }里面可以不用写对应的形参变量名,比如{xxx},但是建议相同

#{}方式是先用?代替参数将SQL语句进行预编译,然后再将参数中的内容替换进来,非法参数内容只会是一个参数,不会在为SQL命令的一部分,可以有效防止SQL注入

只能使用${}的场景

由于#{}会给参数内容加上引号,有些时候需要字段、表名的情况下,SQL会出现问题。

ps:

image-20200927141743719

image-20200927141807589

image-20200927141933259

  • 排序时字段有引号,排序失效
  • 表名有引号,直接报错

所以这些情况下只能使用${}。

评论