本章节将介绍怎样通过 <parameterMap> 和 <parameter>标签实现参数映射。
在之前“MyBatis 入门实例”见到的所有语句都使用了简单的参数形式。但实际上,参数是 MyBatis 非常强大的元素。对于大多数简单的使用场景,你都不需要使用复杂的参数,例如:
<!-- 根据用户ID查找用户信息 --> <select id="findById" parameterType="int" resultMap="RESULT_MAP"> select `user_id`, `name`, `sex`, `age`, `salary`, `borthday`, `face` from `user` where `user_id`=#{userId,jdbcType=INTEGER} </select>
上面的例子定义了一个非常简单的命名参数映射。它的参数类型(parameterType)会被自动设置为 int,这个参数可以随意命名。原始类型或简单数据类型(比如 Integer 和 String)因为没有其它属性,会用它们的值来作为参数。 然而,如果传入一个复杂的对象(如:JavaBean),行为就会有点不一样了。例如:
<!-- 保存用户信息 --> <insert id="saveUser"> INSERT INTO `user`( `user_id`, `name`, `sex`, `age`, `salary`, `borthday`, `face` ) VALUES ( #{userId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{sex,jdbcType=INTEGER}, #{age,jdbcType=VARCHAR}, #{salary,jdbcType=INTEGER}, #{borthday,jdbcType=VARCHAR}, #{face,jdbcType=INTEGER} ) </insert>
如果 UserBean 类型的参数对象传递到了语句中,会查找 userId、name、sex、age、salary、borthday、face 属性,然后将它们的值传入预处理语句的参数中。
MyBatis 对SQL语句传递参数来说,非常简单,不需要我有过多的配置。不过参数映射的功能远不止于此,下面将介绍更多功能:
a)手动指定参数类型
首先,和 MyBatis 的其它部分一样,参数也可以指定一个特殊的数据类型。
#{property, javaType=int, jdbcType=NUMERIC}
和 MyBatis 的其它部分一样,几乎总是可以根据参数对象的类型确定 javaType,除非该对象是一个 HashMap。这个时候,你需要显式指定 javaType 来确保正确的类型处理器(TypeHandler)被使用。
注意:JDBC 要求,如果一个列允许使用 null 值,并且会使用值为 null 的参数,就必须要指定 JDBC 类型(jdbcType)。阅读 PreparedStatement.setNull()的 JavaDoc 来获取更多信息。
b)使用自定义类型处理器
如果 MyBatis 默认的类型处理器不能满足你的需求,你可以自定义类型处理器(后续章节将介绍)。在指定参数的时候可以使用 typeHandler 属性使用自定义类型处理器,比如:
#{age, javaType=int, jdbcType=NUMERIC, typeHandler=MyTypeHandler}
看上去,配置一个参数变得非常的繁琐了,但实际上,很少需要如此繁琐的配置。
c)指定小数点后保留的位数
对于数值类型的参数,我们还可以设置 numericScale 指定小数点后保留的位数。如下:
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
d)映射过程游标
最后,mode 属性允许你指定 IN,OUT 或 INOUT 参数。如果参数的 mode 为 OUT 或 INOUT,将会修改参数对象的属性值,以便作为输出参数返回。 如果 mode 为 OUT(或 INOUT),而且 jdbcType 为 CURSOR(也就是 Oracle 的 REFCURSOR),你必须指定一个 resultMap 引用来将结果集 ResultMap 映射到参数的类型上。要注意这里的 javaType 属性是可选的,如果留空并且 jdbcType 是 CURSOR,它会被自动地被设为 ResultMap。
#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}
MyBatis 也支持很多高级的数据类型,比如结构体(structs),但是当使用 out 参数时,你必须显式设置类型的名称。比如(再次提示,在实际中要像这样不能换行):
#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}
尽管上面这些选项很强大,但大多时候,你只须简单指定属性名,顶多要为可能为空的列指定 jdbcType,其他的事情交给 MyBatis 自己去推断就行了。
#{firstName} #{middleInitial, jdbcType=VARCHAR} #{lastName}