#{}
和${}
都可以从接口输入中的map对象或者pojo对象中获取输入的参数值。例如:
<mapper namespace="com.lzj.mybatis.dao.UserDao">
<select id="getUser" resultType="com.lzj.mybaits.bean.User">
select * from users where name=#{name} and password=#{password}
</select>
</mapper>
或者
<mapper namespace="com.lzj.mybatis.dao.UserDao">
<select id="getUser" resultType="com.lzj.mybaits.bean.User">
select * from users where name=${name} and password=${password}
</select>
</mapper>
上面两种形式都可以通过name和pssword条件查询用户的信息。但是上面两种形式是有本质区别的:Mybatis在处理 形式时,会直接把 {name}和 password获取的值拼接在sql中,例如 {name}的值为”lzj”,${password}的值为”123456”,即mybatis直接处理sql语句为:
select * from users where name='lzj'and password='123456'
mybatis在处理#{}形式时,会通过jdbc中的PreparedStatement先预编译sql语句为下列形式:
select * from users where name=? and password=?
然后在用PreparedStatement把对应占位符处的值代替占位符。
{}比${}的优势
name和
{password}取出的值直接拼装在sql语句中,会有安全问题。
例如name对应的值为:"lzj"#
, 则{name}获取到的值为`"lzj"#`。此时根本不用管password的值为什么了,例如password的值为"XXXX",则{password}获取到值为”XXXX”。mybatis会拼接sql为:
select * from users where name='lzj'# and password='XXXX'
由于sql中# 表示注释的意思,所以mybatis就把上面的语句翻译成了
select * from users where name='lzj'
执行此条语句,根本不再用关系password的值是什么了,因此会有安全问题。
但是用#{}的形式就不会出现这种情况,对于#{}的形式,mybatis会先提前预编译sql语句,然后在将参数设置到sql语句中,防止sql注入。
${}比#{}的优势
大多数情况下,我们应使用#{}的形式,但在有些地方确不成立。原生jdbc不支持占位符的地方我们就可以使用${}进行取值。
比如表的名字处不可以使用占位符,下面是不可以的
select * from #{users}
表名字处不能使用占位符,此时要用下面的形式:
select * from ${users}
例如order by 排序的地方不可以用,下面的形式不可以用
select * from users order by #{name}
应该使用
select * from users order by ${name}
{}其它丰富用法
在mybatis用#{}处理获取输入的参数时,还可以指定其它属性,例如#{name, javaType=String, jdbcType=null}
, 如#{amount, javaType=Double, jdbcType=NUMERIC,numericScale=3}
下面介绍常用的属性
- javaType :表明传入参数的类型
- jdbcType:表明对应数据库中的类型,一般用来处理传入的参数为空的情况。例如:
<select id="getUser" resultType="com.lzj.mybaits.bean.User">
select * from users where name=#{name}
</select>
当name参数传入的值为null时,mybatis会默认传入的name值的类型为数据库other类型 ,对于oracle数据库,不能处理other类型的字段,因此会报不能识别的错误。此时就可以用jdbcType属性指定类型,如
<select id="getUser" resultType="com.lzj.mybaits.bean.User">
select * from users where name=#{name, jdbcType=null}
</select>
当传入的name值的类型为null时,在oracle数据库中会把name字段的值当空来处理。
当name参数传入的值为null时,mybatis会默认传入的name值的类型为数据库other类型 对于mysql数据库,会自动把other类型当做null类型来处理,因此对于mysql数据库中可不用指定jdbcType=null属性,当然也可以指定。
另外,由于在mybatis中默认配置把传入的NULL值类型映射到数据中的other类型,也可以在mybatis的配置文件中指定全局的把传入的NULL类型的参数映射到数据库中指定的类型。例如:
<settings>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>
本文中在conf.xml配置文件中,加上如上配置,当传入的参数为NULL时,mybatis默认映射到数据库中的类型就是NULL类型。
- numericScale:对于java中浮点类型,当传入数据库时可能有若干小数,通过指定numericScale=3,可以指定传入数据库的字段为数值类型,并且只有小数点数后三位。
关于sql注入的问题,参考http://blog.csdn.net/javy_codercoder/article/details/49276653