mybatis占位符分为#{}和${}
#{}是利用jdbc的预编译(PreparedStatement),一个#{}会被解析为一个占位符?。它可以指定变量的类型,比如:#{empCode,jdbcType=VARCHAR}
或#{year,jdbcType=DECIMAL}
,
${}是一个纯粹的String替换,把变量的值直接替换在当前位置
比如: select emp_id from user where code=#{code,jdbcType=VARCHAR}
在log内打印出来为sql为:Preparing:select emp_id from user where code=? Parameters:1(String)
select emp_id from user where code=${code}
在log内打印出来为sql为:select emp_id from user where code=1
可以看到${}会有很大的风险会被sql注入,如果用户恶意操作导致参数为一个sql短语句如: 1 or 1=1,那么使用${},传送给dbms执行的sql变为:select emp_id from user where code=1 or 1=1
,导致数据泄露。而使用#{},则恶意的参数会被预编译为字符串,从而防止sql注入。
所以日常开发中,除了特定场景,比如动态表名,动态排序这种无法使用预编译传变量的场景,要一律使用#{}。
而且使用#{}还继承了预编译的一系列优点:提高执行效率和sql日志可读性高等优点。