#{}和${}的区别
#{}的示例如下


${}的示例如下

如果这种情况下去测试上面的两个方法,那么用${}接受参数的方法会报错。
通过日志我们可以看出,由于password和userName是String类型,所以在查询的时候要加上引号才行。
而当我们用${}的方式来接收参数的时候,(这种方式称为即时SQL),这会直接把参数拼接到SQL语句中,不会添加引号,这就导致我们无法查询到相关数据。
而用#{}的方式来接受参数的时候,(这种方式称为预处理SQL),这种方式会采用占位的方式,并且也会识别我们传进来的参数类型,于是就不会报错。
解决办法,我们可以在SQL语句中手动添加引号:


这样就可以顺利执行了。
除此之外,${}还存在SQL注入问题:
SQL注入问题
下面我们先来看一下这2个SQL语句:


第二个SQL语句中我想传入的password参数是:lisi' or 1='1
但是这条SQL语句却把整个表中的数据都给查询出来了,这是因为我们传如的password这个参数的数值把我们事先定义好的SQL语句进行了修改,因为1='1'这个条件一定是正确的,所以就可以把所有的数据都查询出来了。
像这样通过传入的参数修改原先定义好的SQL语句的问题就叫做SQL注入问题:

如上图所示,这就是当使用${}来接收参数时,出现SQL注入问题的情况。

当我们把同样的参数放在用#{}来接受参数的方法中就不会出现SQL注入问题。
需要注意的是,当我们使用${}来接收参数的时候不一定会出现SQL注入的问题,具体还要看代码是如何书写的。
排序
使用#{}接收参数的形式来实现排序:


通过日志我们可以发现,这个方式并不行,原因是我们使用#{}来接收参数的时候,只要参数是字符串类型,都会加上'',但是asc或者desc却不需要加''。于是这个查询就无法完成。
解决该问题我们可以使用${}来接收参数:
这个时候我们就可以对查询到的结果进行排序:

模糊查询
如果我们使用#{}来接收参数仍然会报错,它实际执行的SQL如下:

此时我们也可以通过使用${}来接受参数的方式来解决这个问题:


但是由于使用${}来接收参数会存在SQL注入问题,于是我们可以使⽤MySql的内置函数 concat() 来处理,实现代码和运行截图如下:

if标签
XML
<insert id="insertUser3">
insert into user_info (username,password,age,
<if test="gender!=null">
gender,
</if>
phone)
VALUES(#{username},#{password},#{age},
<if test="gender!=null">
#{gender},
</if>
#{phone})
</insert>
这个代码表示只有当在插入数据的时候传入了gender的值,才会在新增的数据中有gender这个属性,如果不传入,就是数据库中的默认值:


tirm标签
XML
<insert id="insertUser3">
insert into user_info (
<if test="username!=null">
username
</if>
<if test="password!=null">
,password
</if>
<if test="age!=null">
,age
</if>
<if test="gender!=null">
,gender
</if>
<if test="phone!=null">
,phone
</if>
) VALUES(
<if test="username!=null">
#{username}
</if>
<if test="password!=null">
,#{password}
</if>
<if test="age!=null">
,#{age}
</if>
<if test="gender!=null">
,#{gender}
</if>
<if test="phone!=null">
#{phone})
</if>
</insert>

由于我的测试用例中并没有传入username,所以这就会让SQL语句的password前面多出来一个,
接下来我们就通过tirm标签来解决这个问题:
标签中有如下属性:
prefix:表示整个语句块,以prefix的值作为前缀
suffix:表示整个语句块,以suffix的值作为后缀
prefixOverrides:表示整个语句块要去除掉的前缀
suffixOverrides:表示整个语句块要去除掉的后缀
XML
<trim prefixOverrides=",">
<if test="username!=null">
username
</if>
<if test="password!=null">
,password
</if>
<if test="age!=null">
,age
</if>
<if test="gender!=null">
,gender
</if>
<if test="phone!=null">
,phone
</if>
</trim>
XML
<trim prefixOverrides=",">
<if test="username!=null">
#{username}
</if>
<if test="password!=null">
,#{password}
</if>
<if test="age!=null">
,#{age}
</if>
<if test="gender!=null">
,#{gender}
</if>
<if test="phone!=null">
,#{phone})
</if>
</trim>
我们可以对上面的两个板块使用改标签去掉开头的,
where标签
XML
<select id="selectBycondition" resultType="com.example.mybatis.model.UserInfo">
select * from user_info
<where>
<if test="phone!=null">
phone =#{phone}
</if>
<if test="deleteFlag!=null">
and delete_flag=#{deleteFlag}
</if>
</where>
</select>
当我们不传入任何参数的时候where标签会把上述SQL语句优化为全表查询,当有参数的时候,再根据参数的值来进行查询。
set标签
XML
<update id="updateByCondition">
update user_info
<set>
<if test="age!=null">
age=#{age},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</set>
where id=#{id}
</update>
foreach标签
java
<delete id="batchDelete">
delete from user_info where
id in
<!-- (8,9,10)-->
<foreach collection="list" open="(" close=")" item="ID" separator=",">
#{ID}
</foreach>
</delete>
我们以上述代码为例,open表示我们要拼接的内容的开头是什么,close表示拼接的内容以什么为结尾,item则表示我们传入的集合中的每一个元素的变量名,separator表示元素与元素之间的分隔符,本案例中分隔符就是,index表示索引。
include标签
sql标签中放的是一些SQL语句,当后面我们的SQL语句中还需要用到这些语句的时候,直接通过include标签来获取即可。

