【MyBatis】原来 `${}` 和 `#{}` 藏有这么多坑!

一、引入

众所周知,MyBatis获取参数值的两种方式:${}#{}${} 的本质就是字符串拼接,#{} 的本质就是占位符赋值。

${} 使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;但是 #{} 使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号。

接下来考考大家,下面 的地方应该填 $ 还是 #?(下面参数均为String类型)

xml
复制代码
select * from t_user where username like '%?{username}%'
java
复制代码
select * from t_user where username like "%"?{username}"%"
xml
复制代码
<if test="orderByList != null and orderByList.size() != 0"> ORDER BY <foreach collection="orderByList" separator="," item="orderByItem"> ?{orderByItem} </foreach> </if>

二、解释

第一个案例应为 $,解释:

由于我们使用的是模糊查询,%#{username}% 需要写在一对单引号中,单引号在mysql中表示的是一个字符串;当我们用 #{} 时,并且在执行时,? 会代替 #{} 的时候,? 就存在了 #{} 里面,这个时候就会把 ? 当做字符串的一部分,因此应该使用 ${} 进行字符串拼接

xml
复制代码
select * from t_user where username like '%${username}%'

第二个案例应为 #,解释:

xml
复制代码
select * from t_user where username like "%"#{username}"%"

假设传入的参数 username 的值是 john,使用占位符后的 SQL 语句:

java
复制代码
SELECT * FROM t_user WHERE username LIKE "%john%"

在这种情况下,#{username} 会直接被替换为参数值,而不加引号。

因此,替换后是 "%john%",而不是 "%""%john%""%"


第三个案例应为 $

java
复制代码
<if test="orderByList != null and orderByList.size() != 0"> ORDER BY <foreach collection="orderByList" separator="," item="orderByItem"> ${orderByItem} </foreach> </if>

这是因为如果使用 #{},那么在SQL解析的时候会加上单引号,假设传入的值为 create_time desc, userId desc,那么SQL解析后的结果就为

xml
复制代码
ORDER BY 'create_time desc, userId desc'

此时排序是不生效的,因此需要使用 ${} 让它不自动加单引号

xml
复制代码
ORDER BY create_time desc, userId desc
0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP