MyBatis-映射文件03-两种取值方法(# or $)
#{}:可以获取map中的值或者POJO对象属性的值
${}:可以获取map中的值或者POJO对象属性的值
区别:
#{}:是以预编译的形式设置到sql语句中;PreparedStatement,可以防止sql注入
${}:取出的值直接拼接在sql语句中;会有安全问题
示例:
sql:
select id,last_name,email,gender from tbl_employee where id = ${id} and last_name = #{lastName}
我们调用方法执行该sql,可以发现在控制台输出:
Preparing: select id,last_name,email,gender from tbl_employee where id = 1 and last_name = ?
可以看出使用 $ 取值是直接将值拼接到sql语句中,这样会存在sql注入的安全问题,因此大多数情况下都应该使用 # 来取值
但是,在某些情况下,比如原生sql不支持占位符的地方,例如分表查询,以部分表名为参数,要使用 $ 来取值
示例:
sql:
select id,last_name,email,gender from #{tablename}_employee where id = ${id} and last_name = #{lastName}
此时用#取表名的值会出现sql语法异常错误,而应该使用$来取值
#{}更丰富的用法:
规定参数的一些规则:javaType、jdbcType、mode(存储过程)、numericScale、resultMap、typehandler、jdbcTypeName、expression(未来准备支持的功能)
jdbcType:通常需要在某种特定的条件下被设置
当我们的数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理,比如Oracle数据库(报错),如果向Oracle数据库插入null,会报错为:jdbcType OTHER:无效的类型,因为mybatis对所有的null都映射的是jdbc的OTHER类型,Oracle不能正确处理
解决办法:
1.#{email,jdbcType=NULL}
insert into employee(Employee_ID,last_name,email) values(#{id},#{lastName},#{email,jdbcType=NULL})
2.由于全局配置中:jdbcTypeForNull默认为OTHER,Oracle不支持,修改全局配置文件的 jdbcTypeForNull为NULL
<settings>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>