两个 符号都是取值的,但是他们的区别是什么呢?
一:问题的由来?
最近在工作中有个点击排序的功能调试了许久,终寻因,总结之。
需求是这样的,页面有个table,有一列的上下箭头可点击并排序。对于这种需求,我的mybatis.xml的sql配置写成了如下:
<if test="map.ColumnNameSort!=null and map.ColumnNameSort!=''">
ORDER BY columnName #{map.ColumnNameSort}
</if>
ColumnNameSort即前端传的排序方式,asc或者desc。
然后,预计它的输出应该是类似于下面这样的
ORDER BY columnName desc
但是,真正跑起来时,排序的效果一直没出现,经常一番查找,发现是mybatis 的’#{}’传值的问题,它将sql语句编译成了如下
ORDER BY columnName 'desc' 或者 ORDER BY columnName 'asc'
这样,desc或者asc就成了字符串而不是关键字,sql语句的意思是columnName的别名是desc或者asc,没加排序关键字时默认是正序排序,成了如下
ORDER BY columnName "desc" asc 或者 ORDER BY columnName "asc" asc
排序没效果的问题找到原因了,解决之,mybatis提供了另一种绑定参数的方式–${param},将sql配置改为
ORDER BY columnName ${map.ColumnNameSort}
这样一来,mybatis会直接将ColumnNameSort的值加入sql中,不会转义。正确结果:
ORDER BY columnName desc
二:对比区别
对于mybatis中#和$绑定参数的区别做个总结,避免以后类似的问题发生。
-
#{}
将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #{id},如果传入的值是111,那么解析成sql时的值为order by “111”, 如果传入的值是id,则解析成的sql为order by “id”。 -
${}
将传入的数据直接显示生成在sql中。如:order by
${id},如果传入的值是111,那么解析成sql时的值为order by 111, 如果传入的值是id,则解析成的sql为order
by id。 -
#
方式能够很大程度防止sql注入。 -
$
方式无法防止Sql注入。 -
$
方式一般用于传入数据库对象,例如传入表名. -
一般能用#的就别用$.
在mybatis接口mapper文件中引用传入的参数是通过#{param}或者${param}来使用的。
至于mybatisl中#{}和${}的区别其实很简单,但是之前一直没有理解清楚,网上一堆错误的理解。所以在这里记录一下
其实这个问题很简单。
select * from t_user where name = #{param}
使用#{}就等于使用了PrepareStatement这种占位符的形式。可以防止sql注入等等问题。
select count(*), from t_user group by ${param}
这种group by 字段 ,order by 字段,表名,字段名等没法使用占位符的就需要使用${}
这里展开说一下关于PrepareStatement的好处。
数据库有个功能叫绑定变量,就是针对一条sql预编译生成多个执行计划,如果只是参数改变的重复sql,绑定变量则会提高很大的性能。PrepareStatement就会使用数据库的绑定变量的功能。
TIP:#{} preparement State 预处理 占位符 防止sql 注入