为了安全,能用#的地方就用#方式传参,这样可以有效的防止sql注入攻击
1、#{变量名}可以进行预编译、类型匹配等操作,#{变量名}会转化为jdbc的类型
例:select * from tablename where id = #{id};
假设id的值为12,其中如果数据库字段id为字符型,那么#{id}表示的就是'12',如果id为整型,那么id就是12。
MyBatis会将#{id}解析为一个JDBC预编译语句的参数标记符,把参数部分用占位符?代替。动态解析为:
select * from tablename where id=?;
而传入的参数将会经过PreparedStatement方法的强制类型检查和安全检查等处理,最后作为一个合法的字符串传入。
2、${变量名}不进行数据类型匹配,直接替换
例:select * from tablename where id = ${id};
如果字段id为整型,sql语句就不会出错,但是如果字段id为字符型, 那么sql语句应该写成select * from table where id = '${id}'。
MyBatis只会做简单的字符串替换,在动态SQL解析阶段将会进行变量替换,动态解析为:
select * from tablename where id=12;
3、只可使用${变量名}的场景
如order by 后的排序字段,表名、列名,因为需要替换为不变的常量,则只可使用${}。
例:select * from #{tablename} where id = ${id};
如果表名中使用#{}的话传参为t_user,会变成select * from 't_user',没有这样的表名,这样的话就会报错了,order by 同理。
4、性能考虑
因为预编译语句对象可以重复利用,把一个sql预编译后产生的PreparedStatement对象缓存下来,下次对于同一个sql,可以直接使用缓存的PreparedStatement对象,mybatis默认情况下,对所有的sql进行预编译,这样的话#{}的处理方式性能会相对高些。