Skip to content

#{}与${}有啥不同?从源码的角度来分析!

flysnow911 edited this page Mar 7, 2019 · 2 revisions

GenericTokenParser.java line:19 parse(String text)方法中,就是解析${}占位符的。
如:SELECT * FROM USER_${index} WHERE NAME=#{name} AND age=#{age}
在parse方法中通过定位开始符号:${, 结束符号:},并把相应参数设置进去,sql变成如下:
SELECT * FROM USER_1 WHERE NAME=#{name} AND age=#{age}

SqlSourceBuilder.java line:31中,parse(String originalSql, Class<?> parameterType, Map<String,Object>
additionalParameters),执行#{}的解析。

把sql从上一步:SELECT * FROM USER_1 WHERE NAME=#{name} AND age=#{age}
变成了:
SELECT * FROM USER_1 WHERE NAME=? AND age=?
是不是很熟悉?对了,这就是jdbc认识的sql。

接下来就可以使用:PreparedStatement.set方法设置参数啦!

从这里,看出两者的区别:
#{} : 参数采用预编译方式,可以防止SQL注入
${}: 参数采用直接赋值方式,无法阻止SQL注入攻击
但是并不是所有地方都能使用#{}, jdbc不支持占位符的场合,只能用${}.如以下两种情况:
1.动态指定数据库表:
select * from emp_${year}

2.需要动态的指定查询中的排序字段,此时也只能使用${} select * from dept order by ${name}

并且缓存的key是用SELECT * FROM USER_1 WHERE NAME=? AND age=? 这种形式 加参数 这种形式的,所以能看出来,