${}
是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换,比如${driver}会被静态替换为com.mysql.jdbc.Driver
- 没有办法防止sql注入
- 传入表名
#{}
是 sql 的参数占位符,MyBatis 会将 sql 中的#{}
替换为?号,在 sql 执行前会使用 PreparedStatement 的参数设置方法,按序给 sql 的?号占位符设置参数值,比如 ps.setInt(0, parameterValue),#{item.name}
的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值,相当于 param.getItem().getName()
1、使用场景不同
(1) 在sql语句中,如果要接收传递过来的变量的值的话,必须使用#。因为使用#是通过PreparedStement接口来操作,可以防止sql注入,并且在多次执行sql语句时可以提高效率。
(2) $ 只是简单的字符串拼接而已,所以要特别小心sql注入问题。对于sql语句中非变量部分,那就可以使用 $ ,比如$方式一般用于传入数据库对象(如传入表名)。
(3) 如果在sql语句中能同时使用#和$的时候,最好使用#。
2.实现方式不同
(1) $作用相等于是字符串拼接
相当于使用StringBuffer的append方法将 ${username} $ 追加在select username,pass from t_login where username=后面,拼接在一起。
(2) #作用相当于变量值替换
相当于使用PreparedStement接口来对#{username}#来进行赋值操作,当传入的有 "or 1=1"的时候将会查出所有内容,这就是sql注入危险。