#{} 和 ${} 的区别
最近在回顾mybatis的相关内容时,发现这个问题是面试官比较爱问的一个问题,如果仅仅对mybatis而言,目前市面上的答案可以应对,但如果跳出mybatis的范围似乎市面上的答案就不是很满足的样子。为什么这么说呢? 因为 #{} 和 ${} 的使用并不仅仅在mybatis上使用,在我们常用的spring框架中也有对应的用法。
首先说说Mybatis吧!
对象关系映射(英语:Object Relational Mapping),简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。
Mybatis作为半自动化orm框架,作为他的半自动的来名是因为其需要手动写sql,而全自动Hibenate,是只需要通过面向对象方式的操作,就可以实现对数据库的操作。
对于手写sql必然会有参数的传递,这就会带来一个问题就是sql注入问题,在jdbc中为了解决sql注入问题可以使用PreparedStatement类对sql进行预编译,对传入的值进行了限制从而解决的sql注入问题的产生。在mybatis中提供了两种方式,${} 和#{}对其进行注入参数,#{}的方式就是采用预编译PreparedStatement的形式对属性进行注入的,将#{}的形式转换为?,然后参数将问号进行替换,最后将完整的sql进行交给mysql进行执行,但是他这样的方式并不适用于全部的场景,例如查询需要将排序的是升序还是降序进行传参或者表名为可变时就不能使用#{},而要用 ${}, 对于 ${}则是对sql进行拼接,就像Statement一样,没有通过预编译sql。
例如:
#{}
select * from tbl_user where username = #{username} and password = #{password}
会被解析为:
select * from tbl_user where username = ? and password =?
传入参数后:
select * from tbl_user where username = "admmin" and password = "123456";
${}
select * from tbl_user where username = ${username} and password =${password}
传入参数:
select * from tbl_user where username = admin and password = 123456
-- 这样的语句会抛出异常SqlException
#{}
select * from tbl_user where username = #{username} order by amount #{order}
会被解析为:
select * from tbl_user where username = ? order by amount ?
传入参数后为:
select * from tbl_user where username = "admin" order by amount "ASC"
-- 这样的语句会抛出异常SqlException
${}
select * from tbl_user where username = #{username} order by amount ${order}
传入参数后为:
select * from tbl_user where username = "amdin" order by amount Asc
mybatis中的${}和#{} 的区别就介绍到这,下面将介绍spring中 ${}和#{} 的区别。
在spring中的 ${} 和 #{} 的区别主要是用在@Value注解通过读取properties文件以及对其他的表达式值得注入属性的注入。
对于${}相当于占位符,在注入时根据系统环境变量、jvm环境变量、以及类路径下得properties文件中的字段进行注入。
而#{} 相当于el表达式的形式,spring会对该表达式进行解析得到结果后对其进行注入,这个结果可能是字符串也可能是bean对象,但要注意的是注入的元素要与被注入的属性的类型一致,否则将会报出类型不匹配的异常。
具体示例请参见,本人所发布的@Value注解