使用拼接符还是占位符?
使用区别
占位符#
相比于拼接符$
最大的区别就是能防止SQL注入,所以原则上应该尽可能的使用#
而不是$
,那么应该在什么情况下使用$
?
由这个经典的order by 问题引出
在sql里,任意一句select 语句加上order by 关键字 (或是已有order by关键字),然后加上'dafafadfagdghfdc 23423'
或者是 ''
或者是 23141234
或者再加一个, ''
这样乱七八糟的参数是不影响sql的’正常运行’的,这意味着什么?意味着如果order by 后跟的是一个参数,那么如果参数和关键字都被引号给包住,那么无论是参数还是关键字都不起任何作用,而且不会报任何错误,例如
注意代码高亮
order by "id desc"
-- 而不是
order by id desc
想要排序的一定是某个或者多个字段,那么
涉及到字段名传参的时候就不能使用#
,而得使用$
仅仅是字段值参数的传递,需要使用#
需要保持良好习惯的是,即使是用拼接符,在涉及到传值的时候,也手动为参数两边加引号,防止下面这种类型的注入
WHERE U_account = 'xxxxxx or 1=1 -- '
底层区别
#
占位符在生成statement
会用?
占位符,由JDBC的preparedStatement
对象使用set
赋值把SQL中的?
用变量填充
$
占位符会在statementHandler
对象处理参数调用parameterize方法
直接替换为变量的值
参考
#
将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #{user_id}
,如果传入的值是111,那么解析成sql时的值为order by "111"
, 如果传入的值是id,则解析成的sql为order by "id"
。$
将传入的数据直接显示生成在sql中。如:order by ${user_id}
,如果传入的值是111,那么解析成sql时的值为order by 111
, 如果传入的值是id,则解析成的sql为order by id
。#
方式能够很大程度防止sql注入。$
方式无法防止Sql注入。$
方式一般用于传入数据库对象,例如传入表名。- 一般能用
#
的就别用$
。
ps: 在使用mybatis中还遇到<![CDATA[]]>的用法,在该符号内的语句,将不会被当成字符串来处理,而是直接当成sql语句,比如要执行一个存储过程。