1. MyBatis 占位符 # 和 $
默认情况下,使用 #{} 参数语法时,MyBatis 会创建 PrepareStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。这样做更安全,更迅速,通常也是首选做法。
1.1 MyBatis 占位符之 #
- #{} 占位符,MyBatis 会创建 PrepareStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样),可以有效防止 SQL 注入,更迅速;
示例:
<select id="selectById">
select * from user where id = #{id}
</select>
1.2 MyBatis 占位符之 $
- ${} 占位符,创建 Statement 对象,执行 SQL 语句的效率相对于 #{} 占位符低;
- ${} 占位符,直接使用字符串填充拼接,有 SQL 注入的风险;
<select id="selectById">
select * from user where id = ${id}
</select>
1.3 #{} 和 ${} 占位符混合使用
有时候你就是想直接在 SQL 语句中直接插入一个不转移的字符串。比如 ORDER BY 子句,这个时候你可以:
ORDER BY ${columnName}
当 SQL 语句中的元数据(表名或列名) 是动态生成的时候,字符串替换将会非常有用:
不使用 ${} 占位符写法,可能是这样的:
<select id="selectById">
select * from user where id = #{id}
<select>
<select id="selectByName">
select * from user where name = #{name}
<select>
<select id="selectByEmail">
select * from user where email = #{email}
<select>
使用 ${} 占位符写法,可能是这样的:
<select id="selectByColumn">
select * from user where ${column}=#{value}
</select>
其中 ${column} 会被直接替换,而 #{value} 会使用 ? 预处理。这种方式也同样适用于替换表名的情况。
提示:
用 ${} 占位符方式接受用户的输入,并用作语句参数是不安全的,会导致潜在的 SQL 注入攻击。因此,要么不允许用户输入这些字段,要么自行转义并检验这些参数。