一.概念:都是SQL中动态的传入参数的方式
#{}:预编译处理,JDBC预编译(prepared statement)语句的参数标记符,先被解析为?参数占位符,之后再通过预编译的set进行赋值。解析之后会将String类型的数据自动加上引号,其他数据类型不会。流程:数据库驱动在发送 sql 语句和参数给 DBMS 之前对 sql 语句进行编译,这样 DBMS 执行 sql 时,就不需要重新编译。
${}: 字符串替换,纯粹的string替换,在动态SQL解析阶段将会进行变量替换,直接替换成变量的值。解析之后是什么就是什么。发生在动态解析过程、
预防SQL注入:sql注入就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,在编写sql时永远不要信任用户的输入,必须认定用户的输入是不安全的,提前在sql中进行数据预防处理,#{}就是其中的一种方式,PreparedStatement不允许在插入参数时改变SQL语句的逻辑结构,其次是SQL语句在程序运行前进行了预编译,在操作数据库之前sql语句已经被数据库分析,编译和优化对应的执行方式也会被缓存下来而后对数据库进行查询,之后即使有敏感字符的参数也不会作为一个SQL指令来执行了,简短的说就是SQL注入发生在编译的过程,预编译提前对SQL语句进行预编译,而其后注入的参数将不会进行SQL编译。
举例
String SQL=SELECT *FROM user WHERE password=${password}
假设用户输入的是 123or1=1
${}传递的数据当成sql语句中的一部分
最后的语句解析为SELECT *FROM user WHERE password=123 or 1=1
相当于SELECT *FROM user,后果可想而知
#{}
#{}传递的数据都会被当成一个字符串,自动的加上一个双引号
最后的语句解析为SELECT *FROM user WHERE “password=123 or 1=1”
避免了恶意行为的产生
特殊情况:order by #{type}/${type}
#{type}解析为order by "type",显然是有问题的
${type}解析为order by type正确语句