Bootstrap

MyBatis SQL语句 #{} 和 ${}的区别

在这里插入图片描述

T04BF

👋专栏: 算法|JAVA|MySQL|C语言

🫵 今天你敲代码了吗

关于 #{} 和 ${}

MyBatis参数赋值有两种方式:#{} 和 ${}

1. Integer类型的参数

(1)${}

<update id="updateUser">
  update userinfo set phone = ${phone} where id = ${id}
</update>

测试结果:
image.png
此时得到的参数ID是直接拼接在sql语句里面了,这种是"即时SQL"
(2)#{}

<update id="updateUser">
  update userinfo set phone = ${phone} where id = #{id}
</update>

image.png
与前一种方式不一致的是,输入的参数不是在后面直接拼接,而是使用?进行占位,这种是"预编译SQL"

2.String 类型的参数

(1) ${}

<select id="queryUserByUsername" resultMap="XMLBaseMap">
  select * from userinfo where username = #{username}
</select>

测试:

@Test
void queryUserByUsername() {
    System.out.println(userInfoMapper.queryUserByUsername("zhangsan"));
}

执行结果:
image.png
(2) #{}

<select id="queryUserByUsername" resultMap="XMLBaseMap">
  select * from userinfo where username = ${username}
</select>

测试结果:
image.png
此时的SQL语句是:
image.png
可以看到,这次的参数也是直接拼接在sql语句后面了,但是字符串作为参数的时候,需要加上''
使用${} 不会自动拼接引号
因此需要我们自己添加引号
image.png

3. #{} 和 ${} 的区别

3.1 性能问题:

绝大部分情况下,一条SQL语句是会被重复执行的,或者每次执行的参数不一样(如where后面的条件参数)
如果每次都需要经过上面的语法解析,SQL优化,SQL编译等,则会影响效率
而预编译SQL,编译一次之后会将编译后的SQL语句缓存起来,后面再执行的时候,只是参数不同就不会再次编译,提高了效率

3.2 安全问题

使用预编译SQL可以防止SQL注入的问题

SQL注入:是通过输入操作的数据来修改事先定义好的sql语句,以达到执行代码对服务器进行攻击的方法
比如: ' or 1 = '1
如果执行以下代码:

select * from userinfo where username = ‘${username}’

' or 1 = '1作为字符串参数传进去,就会得到下面的SQL语句:
image.png
那么如果此时是delete,后果不堪设想

那么是不是说由于SQL注入的问题,就必须无脑使用#{}??
实际上,在一些需求里面,我们不得不使用${}
如排序功能
如果使用#{}:

<select id="queryUserInfoByOrder" resultMap="XMLBaseMap">
  select * from userinfo order by id #{order}
</select>

此时需要将order作为字符串传入
但是由于使用#{} 会自动加上引号,就会出现问题

<select id="queryUserInfoByOrder" resultMap="XMLBaseMap">
  select * from userinfo order by id #{order}
</select>

执行结果:
image.png
这种情况就不得不使用${}了,但是怎么解决SQL注入问题呢??
– 通过枚举,页面或者判断的方式控制参数,只能为desc 或 asc
like查询
like使用#{} 会报错
image.png
还是由于#{} 自动加引号导致的
此时还是不得不使用${}
image.png
还是得解决SQL注入的问题:
在sql里面,CONCAT函数用于将两个或多个字符串值连接成一个字符串,可以用于解决这个问题

<select id="queryUserInfoLike" resultMap="XMLBaseMap">
  select * from userinfo where username like concat('%',#{key},'%');
</select>

image.png

感谢您的访问!!期待您的关注!!!

在这里插入图片描述

T04BF

🫵 今天记得敲代码
;