#{} 表示占位,和参数名无关
${} 表示拼接,和参数类型无关
在Mapper.xml映射文件中,经常使用#{属性名} 来作为SQL语句的占位符,来映射Sql需要的实际参数
也就是说:#{}就是一个预编译的占位符作用
#{}的用法
如果接口中方法只有一个参数
只有一个参数时,入参可以是以下情况:
1)Java的基本类型、基本类型包装类、String类型等
这种情况下,#{}中写什么都无所谓,因为MyBatis会把实际参数直接传入这个位置,不管参数名称和类型
2)Java引用类型,不如User这样的对象
这种情况下,MyBatis会把User对象中的属性名和属性值以键值对形式保存到一个类似Map的结构中。
因此,当我们用#{属性名} 来取值时,其实就相当于根据键查找值。可以直接获取到User的属性值!
3)HashMap类型(很少用)
如果参数是一个HashMap,这样就非常方便了,我们可以直接用 #{键的名称} 来获取到对应的值。这种方式与上面的方式2类似,因此很少使用
结论:如果是一个参数,
简单数据类型:#{}不管写什么都可以获取值
对象类型:#{}可以根据参数对象中的属性名获取属性值
Map类型:#{}可以根据Map的键来取到对应的值
如果有多个参数
4)使用@Param注解来指定参数名称
${}的用法
${}获取参数的方式
${}底层其实使用的是OGNL表达式。在处理参数时,与#{}有很大差别。
1)当只有一个参数时:
MyBatis底层会把这个参数 以键为’value’的形式存入Map中,因此取值的时候,必须${value},或者通过@Param注解
2)当有多个参数时:
此时必须以${param1}、${param2}方式或者@Param注解方式来获取参数
最后的结论:无论是1个参数,还是多个参数,都使用@Param注解,然后通过注解的中指定的名称取值
${}获取参数的问题
注意事项:
1、${}在取值时,并不会进行预编译,而是直接拼接SQL语句:
这样无法防止SQL注入问题
2、${}取值的时候,需要自己判断参数数据类型,如果是字符串,还得自己加引号:”${}”
因此,一般在SQL语句中,如果要获取参数,一般我们都会使用#{},而不是${}
#和$的区别与联系
总结
1.#是占位符,会对SQL进行预编译,相当于?; $是做SQL拼接,有SQL注入的隐患
2.#不需要关注数据类型,Mybatis自动实现类型转换。 $必须自己判断数据类型
联系:
两者都支持通过@Param注解 指定参数名称,来获取参数值。推荐这种方式!