MyBatis中 # 和 $ 区别
在使用mybatis框架开发项目编写SQL语句的时候,经常需要用到变量替换值,那么用来替换变量值的操作经常用到$和#这两个符号,同样在一些Java面试中也经常被问到它们的区别。那么它们在使用上面有什么区别呢?下面根据使用情况分析总结,两者的区别。
#占位符的特点
1. MyBatis处理 #{ } 占位符,使用的 JDBC 对象是PreparedStatement 对象,执行sql语句的效率更高。
2. 使用PreparedStatement 对象,能够避免 sql 注入,使得sql语句的执行更加安全。
3. #{ } 常常作为列值使用,位于sql语句中等号的右侧;#{ } 位置的值与数据类型是相关的。
$占位符的特点
1. MyBatis处理 ${ } 占位符,使用的 JDBC 对象是 Statement 对象,执行sql语句的效率相对于 #{ } 占位符要更低。
2. ${ } 占位符的值,使用的是字符串连接的方式,有 sql 注入的风险,同时也存在代码安全的问题。
3. ${ } 占位符中的数据是原模原样的,不会区分数据类型。
4. ${ } 占位符常用作表名或列名,这里推荐在能保证数据安全的情况下使用 ${ }。
SQL 注入
${}方式是将形参和SQL语句直接拼接形成完整的SQL命令后,再进行编译,所以可以通过精心设计的形参变量的值,来改变原SQL语句的使用意图从而产生安全隐患,即为SQL注入攻击。现举例说明:
现有Mapper映射文件如下:
<select id="findByName" parameterType="String" resultMap="studentResultMap"> SELECT * FROM user WHERE username='${value}' </select>
当 username = "' OR 1=1 OR '" 传入后,${}将变量内容直接和SQL语句进行拼接,结果如下:
SELECT * FROM user WHERE username='' OR 1=1 OR '';
显而易见,上述语句将把整个数据库内容直接暴露出来了
#{}方式则是先用占位符代替参数将SQL语句先进行预编译,然后再将参数中的内容替换进来。由于SQL语句已经被预编译过,其SQL意图将无法通过非法的参数内容实现更改,其参数中的内容,无法变为SQL命令的一部分。故,#{}可以防止SQL注入而${}却不行
#和$使用场景不同
(1)在sql语句中,如果要接收传递过来的变量的值的话,必须使用#。因为使用#是通过PreparedStement接口来操作,可以防止sql注入,并且在多次执行sql语句时可以提高效率。
(2)$只是简单的字符串拼接而已,所以要特别小心sql注入问题。对于sql语句中非变量部分,那就可以使用$,比如$方式一般用于传入数据库对象(如传入表名)。
例如:
select * from ${tableName},$ 对于不同的表执行统一的查询操作时,就可以使用$来完成。
(3)如果在sql语句中能同时使用#和$的时候,最好使用#。
本文来自博客园,作者:hellowworld!,转载请注明原文链接:https://www.cnblogs.com/zhangsai/p/17723011.html
posted on 2023-09-22 17:32 hellowworld! 阅读(40) 评论(0) 编辑 收藏 举报