直接替换是指:是MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值。
预编译处理是指:MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号,使⽤ PreparedStatement 的 set ⽅法来赋值。
$是直接替换,传入的SQL参数若遇到String类型时,不会自动加单/双引号,就会报错,必须加单/双引号才不出错。并且还有sql注入问题。不过$也有自己的使用场景,比如排序,传入desc,asc字符串时,是不需要加单/双引号的。此时就可以用$,并且这两个字符串不让用户自己传,直接给升序,降序按钮,也就避免了sql注入风险。能发生SQL注入主要还是为用户提供了输入框,用户能传参。
而#无论是Integer类型,还是String类型,都会提前预编译,预编译SQL,而且预编译SQL的性能更高。遇到String类型会自动加单/双引号。
以模糊查询为例,${}和#{}的使用区别
代码演示,所传参数后跟 ' or '1=1 。就会查出全结果集。
bookMapper.getBookByN("平凡的世界' or '1=1"); //传入参数
select * from book_info where book_name = '${bookName}'; //SQL语句
SQL日志打印:
insert into userinfo {
username,
password,
nickname,
//test中的sex是属性,不是字段
sex,
}
birthday
)values (
#{username},
#{password},
#{nickname},
//test中的这里的sex是属性
#{sex},
#{birthday}
)
注意 test 中的 sex,是传⼊对象中的属性,不是数据库字段。
prefix:表示整个语句块,以prefix的值作为前缀
suffix:表示整个语句块,以suffix的值作为后缀
prefixOverrides:表示整个语句块要去除掉的前缀
suffixOverrides:表示整个语句块要去除掉的后缀
insert into userinfo
username, //别忘记逗号
password, //test中的是属性,不是字段
nickname,
sex,
birthday,
#{username},
#{nickname},
#{sex},
#{birthday},
以上标签也可以使⽤
//parameterType 为传入参数的类型
update userinfo
username = #{username},
password = #{password},
nickname = #{nickname},
sex = #{sex},
birthday = #{birthday},
where = #{id}
以上标签也可以使⽤
// collection 集合类型 item集合名
delete from userinfo where id in
#{list}