解答

a、#{}是预编译处理,${}是字符串替换。
b、Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;
c、Mybatis 在处理${}时,就是把${}替换成变量的值。
d、使用#{}可以有效的防止 SQL 注入,提高系统安全性

源码位置 参考 https://www.cnblogs.com/warrior4236/p/13145132.html

二、拓展

1、什么是sql注入?为什么#能防止sql注入

sql注入:delete from table where id=${},这这时可以填入一个值 1,但是也可以填入 1 OR 1=1
即:delete
from table where id= 1 OR 1=1,这时就会删除所有数据,这就是漏洞!
为什么#能防止sql注入呢?因为#用到了预编译(prepareStatement)。

2、什么是预编译

一条sql语句执行,需要进过语义解析,指定执行计划,执行并返回结果 而预编译的sql在执行sql的时候则直接进行执行计划,不会在进行语义解析,也就是DB不会在进行编译,而是直接执行编译过的sql。

所以 delete from table where id=#{},经过mybatis的时候,会被写成 delete from table where id= ?,然后使用prepareStatement进行预编译,而其后注入的参数将不会再进行SQL编译。也就是说其后注入进来的参数 系统将不会认为它会是一条SQL语句,而默认其是一条一个参数,
即delete * from table where id=1,如果值是 1 or 1=1,(id在数据库中是int类型)那会报错,因为此时mysql会把1 or 1=1当成一个值,这明显是错误的。
如果是delete from user where username = #{name},此时name 是 “king or 1 =1”,那sql也只会是delete from user where username = “king or 1 =1”,没有任何影响。