MyBatis的参数映射不同于字段映射,参数映射中的"参数"是指传入SQL语句的参数,而字段映射指的是将JDBC ResultSets数据映射成JavaBean。
MyBatis的参数映射配置
MyBatis的参数映射利用的属性是:parameterType。
parameterType,将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)
基本类型
只含或者不含`parameterType
`
SQL语句
User getUserById(Integer id);
<select id="getUserById" resultType="User">
select * from user where id=#{id}
</select>
上面的这个示例说明了一个非常简单的命名参数映射。鉴于参数类型(parameterType)会被自动设置为 int,这个参数可以随意命名。原始类型或简单数据类型(比如 Integer 和 String)因为没有其它属性,会用它们的值来作为参数。 然而,如果传入一个复杂的对象,行为就会有点不一样了
只含@Param
用注解来简化xml配置的时候,@Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值,正确的将参数传入sql语句中
这种就会只按照名字匹配,而不是按照类型匹配了,如果名字不同,则会异常
User getUserById(@Param("ids") Integer id);
<select id="getUserById" resultType="User" parameterType="integer">
select * from user where id=#{ids}
</select>
若parameterType
和注解@Param都包含,则此时按名字匹配,这个时候其实parameterType已经没有什么作用了
复杂类型
Java Bean
如果 User 类型的参数对象传递到了语句中,会查找 id、name和 pwd属性,然后将它们的值传入预处理语句的参数中。对传递语句参数来说
User insertUser(User user);
<insert id="insertUser">
insert into user(id, name, pwd)
values(id, name, pwd)
</insert>
如果入参是JavaBean , 则不能使用@Param
list集合
只包含parameterType,则当前就是表示只用这个的类型,则在xml中进行循环的时候,要按照类型来识别了
List<User> getUserByIds(List<String> ids);
如下collection中必须用list才行,因为这里已经是按照类型来进行识别了
<select id="getUserByIds" parameterType="list" resultType="com.yang.entity.User">
select id, name, pwd
from user where id in (
<foreach collection="list" item="id" separator=",">
#{id}
</foreach>
)
</select>
使用@parm
则表示当前是要用名字来进行识别,则就没有必要写parameterType了,也就是两者都存在的时候,其中一个parameterType是会失效的
List<User> getUserByIds(@Param("idList") List<String> ids);
<select id="getUserByIds" resultType="com.yang.entity.User">
select id, name, pwd
from user where id in (
<foreach collection="idList" item="id" separator=",">
#{id}
</foreach>
)
</select>
map集合
这种其实就是按照类型匹配,这个时候,对应的占位符采用的是只有key
User insertUser(HashMap<String, Object> map);
<insert id="insertUser" parameterType="hashmap">
insert into user(id, name, pwd)
values(id, name, pwd)
</insert>
使用@Param注解
如果是注解,则是按照名字匹配
User insertUser(@Param("maps") HashMap<String, Object> map);
<insert id="insertUser" parameterType="hashmap">
insert into user(id, name, pwd)
values(maps.id, maps.name, maps.pwd)
</insert>
多个参数
对于多参数的,则就无法直接通过参数类型来识别了,而是必须要通过@Param来进行识别
User getUserByIdAndName(@Param("id") String id, @Param("name") String name);
<select id="getUserByIdAndName" resultType="com.yang.entity.User">
select * from user
where id=#{id} and name=#{name}
</select>
JdbcType类型
在Mybatis明文建议在映射字段数据时需要将JdbcType属性加上,这样相对来说是比较安全的
备注:提示 JDBC 要求,如果一个列允许使用 null 值,并且会使用值为 null 的参数,就必须要指定 JDBC 类型(jdbcType)
<insert id="saveRole">
insert into role values (
#{roleId},
#{name},
#{remarks},
#{orderNo},
#{createBy,jdbcType=VARCHAR},
#{createDept,jdbcType=VARCHAR},
#{createTime,jdbcType=DATE},
#{updateBy,jdbcType=VARCHAR},
#{updateTime,jdbcType=DATE}
)
</insert>
这样,保证了前四种是不能为空的前提下,而后面几项为空时也不至于程序报错。如果createBy为空,插入的时候mybatis不知道具体转换成什么jdbcType类型,通常会使用一个默认设置,虽然默认配置一般情况下不会出错,但是遇到个别情况还是会有问题的。Mybatis经常出现的:无效的列类型: 1111 错误,就是因为没有设置JdbcType造成的。
#{height,javaType=double, jdbcType=NUMERIC, numericScale=2}
对于数值类型,还可以设置 numericScale 指定小数点后保留的位数。