虽然在myBatis中参数大部分都很简单,但是我们还是要了解参数的使用,我们可以通过定制参数的类型去让对应的typeHandler去处理它们,通过指定对应的jdbcType,javaType我们可以明确使用哪个typeHandler去处理参数,或者定制一些特殊的东西,但是要注意的是:定义参数属性的时候,MyBatis不允许换行。
1.参数配置
我们可以传入一个简单的参数,比如int,double等,也可以传入JavaBean,这些我们都了解过,有时候我们需要处理一些特殊的情况,我们可以指定特定的类型,以确定使用哪个typeHandler处理它们,以便我们进行特殊的处理。
例子:
#{age,javaType=int,jdbcType=MUMERIC}
我们可以指定哪个typeHandler去处理参数
#{age,javaType=int,jdbcType=MUERIC,typeHandler=MyTypeHander}
此外,我们还可以对一些数值型的参数设置其保存的精度
#{price,javaType=double,jdbcType=MUERIC,typeHandler=MyTypeHander,numericScale=2}
从上面可见MyBatis映射器可以通过EL的功能帮助完成我们所需要的多种功能。
2.存储过程支持
对于存储过程而言,存在三种参数,IN , OUT , INOUT。
MyBatis的参数规则为其提供了良好的支持,我们通过制定mode属性来确定其是哪一种参数,它的选项有三种:IN , OUT , INOUT。
当参数为OUT时,或者为INOUT的时候,MyBatis会将存储过程返回的结果设置到你定制的参数中。
当你返回的是一个游标(也就是我们定制jdbcType=CURSOR)的时候,你还需要去设置resultMap以便MyBatis将存储过程的参数映射到对应的类型,这时MyBatis就会通过你所设置的resultMap自动为你设置映射结果。
例子:
#{role,mode=OUT,jdbcType=CURSOR,javaType=ResultSet,resultMap=roleResultMap}
上面的javaType是可选的,即使你不指定它,MyBatis也会自动检测它。
MyBatis还支持一些高级特性,比如说结构体,但是当注册参数的时候,你就需要去指定语句类型的名称(jdbcTypeName),比如:
#{role,mode=OUT,jdbcType=STRUCT,jdbcTypeName=MY_TYPE,resultMap=droleResultMap}
在大部分情况下MyBatis都会去推断你返回数据的类型,所以大部分情况下你都无需去配置参数类型和结果类型。要我们设置的往往只是可能返回为空的字段类型而已,因为null值,MyBatis无法判断其类型。
例如:
#{roleNo},#{roleName},#{note,jdbcType=VARCHAR}
上面的对于note而言,可能是返回为空的,用jdbcType=VARCHAR明确告知MyBatis,让它被StringTypeHandler处理。
3.特殊字符串替换和处理(#和$)
在MyBatis中,我们常常传递字符串,我们设置的参数#(name)在大部分情况下MyBatis会用创建预编译的语句,然后MyBaits为它设值,而有时候我们需要的是传递SQL语句本身,而不是SQL所需要的参数。例如,在一些动态表格中,我们要传递SQL的列名,根据某些列进行排序,或者传递列名给SQL都是比较常见的场景,MyBatis对这样的场景进行了支持。
例如:在程序中传递变量columns=" col1,col2,col3…" 给SQL, 让其组装成为SQL语句。我们当然不想被MyBatis像处理普通参数一样 把它设为" col1,col2,col3…" ,那么我们就可以写成如下语句:
select ${columns} from t_tablename
这样MyBatis就不会帮我们转译columns,而变为直出,而不是作为SQL的参数进行设置了。只是这样是对SQL而言是不安全的。
sql元素的意义,在于我们可以定义一串SQL语句的组成部分,其他的语句可以通过引用来使用它。
例如:
<sql id="role_columns">
id ,role_name ,note
</sql>
<select parameterType="long" id="getRole" resultMap = "roleMap">
select <indlude refid="role_columns"/> from t_role where id =#{id}
</select>
<select parameterType="map" id="findRoles">
select id, role_name, note from t_role
where role_name like concat ('%', #{roleName}, '%')
and note like concat('%',#{note},'%')
</select>
上面代码我们开始用sql元素定义了role_columns, 它可以很方便地使用include元素的refid属性进行引用,从而达到重用的功能。
上面只是一个简单的例子,在真实的环境中我们也可以制定参数来使用它们:
<sql id="role_columns">
#{prefix}.role_no, #{prefix}.role_name, #{prefix}.note
</sql>
<select parameterType="string" id="getRole" resultMap="roleResultMap">
select
<include refid="role_columns">
<property name="prefix" value="r" />
</include>
from t_role r where role_no =#{roleNo}
</select>
这样就可以给MyBatis加入参数,我们还可以这样给refid一个参数值,由程序制定引入SQL,如下:
<sql id="someinclude">
select * from <include refid="${tableName}" />
</sql>
这样就实现一处定义多处引用,大大减少工作量。