(转)MyBatis在插⼊的数据有空值时,可能为空的字段都要设
置jdbcType
1 引⾔
前⾯的所有语句中你所见到的都是简单参数的例⼦,实际上参数是 MyBatis ⾮常强⼤的元素,对于简单的做法, 90% 的情况参数都很少,⽐如:
<select id="selectUsers" resultType="User">
select id, username, password
from users
where id = #{id}
</select>
上⾯的这个⽰例说明了⼀个⾮常简单的命名参数映射。参数类型被设置为int,这样这个参数就可以被设置成任何内容。
原⽣的类型或简单数据类型(⽐如整型和字符串)因为没有相关属性,它会完全⽤参数值来替代。然⽽,如果传⼊⼀个复杂的对象,⾏为就会有⼀点不同了。⽐如:
<insert id="insertUser" parameterType="User">
insert into users (id, username, password)
空字符串是什么values (#{id}, #{username}, #{password})
</insert>
如果 User 类型的参数对象传递到了语句中,id、username 和 password 属性将会被查,然后将它们的值传⼊预处理语句的参数中。
这点对于向语句中传参是⽐较好的⽽且⼜简单,不过参数映射的功能远不⽌于此。
2 Mybitis参数类型
⾸先,像 MyBatis 的其他部分⼀样,参数也可以指定⼀个特殊的数据类型。
#{property,javaType=int,jdbcType=NUMERIC}
像 MyBatis 的剩余部分⼀样,javaType 通常可以从参数对象中来去确定,前提是只要对象不是⼀个 HashMap。那么 javaType 应该被确定来保证使⽤正确类型处理器。
NOTE 如果 null 被当作值来传递,对于所有可能为空的列,需要设置参数的jdbcType。你可以⾃⼰通过阅读预处理语句的 setNull() ⽅法的JavaDocs ⽂档来研究这种情况。
为了以后定制类型处理⽅式,你也可以指定⼀个特殊的类型处理器类(或别名),⽐如:
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
尽管看起来配置变得越来越繁琐,但实际上是很少去设置它们。
对于数值类型,还有⼀个⼩数保留位数的设置,来确定⼩数点后保留的位数。
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
最后,mode 属性允许你指定 IN,OUT 或 INOUT 参数。
如果参数为 OUT 或 INOUT,参数对象属性的真实值将会被改变,就像你在获取输出参数时所期望的那样。如果 mode 为 OUT(或INOUT),⽽且 jdbcType 为 CURSOR(也就是 Oracle 的 REFCURSOR),
你必须指定⼀个 resultMap 来映射结果集到参数类型。要注意这⾥的 javaType 属性是可选的,如果左边的空⽩是 jdbcType 的 CURSOR 类型,它会⾃动地被设置为结果集。
#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}
MyBatis 也⽀持很多⾼级的数据类型,⽐如结构体,但是当注册 out 参数时你必须告诉它语句类型名称。⽐如(再次提⽰,在实际中要像这样不能换⾏):
#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}
尽管所有这些强⼤的选项很多时候你只简单指定属性名,其他的事情 MyBatis 会⾃⼰去推断,最多你需要为可能为空的列名指定jdbcType。
#{firstName}
#{middleInitial,jdbcType=VARCHAR}
#{lastName}
3 字符串替换
默认情况下,使⽤#{}格式的语法会导致 MyBatis 创建预处理语句属性并安全地设置值(⽐如?)。这样做更安全,更迅速,通常也是⾸选做法,不过有时你只是想直接在 SQL 语句中插⼊⼀个不改变的字符串。⽐如,像 ORDER BY,你可以这样来使⽤:
ORDER BY ${columnName}
这⾥ MyBatis 不会修改或转义字符串。
NOTE 以这种⽅式接受从⽤户输出的内容并提供给语句中不变的字符串是不安全的,会导致潜在的 SQL 注⼊攻击,因此要么不允许⽤户输⼊这些字段,要么⾃⾏转义并检验。
3.1 #{}与${}
注意以下两个符号的使⽤:
#{}(ibatis为:##):MyBatis创建预处理语句属性从⽽设置安全的值(⽐如?)。常⽤作查询条件的值,例如:where name=#{value}。
该参数可以指定⼀个确切的数据类型,例如: #{property,javaType=int,jdbcType=NUMERIC}.
${}(ibatis为:$$): MyBatis不会修改或转义字符串,将会直接在SQL语句中插⼊⼀个不改变的字符串,常⽤于拼凑sql的实体部分,
例如:select * from ${tableName}
在执⾏SQL时MyBatis会⾃动通过对象中的属性给SQL中参数赋值,它会⾃动将Java类型转换成数据库的类型。⽽⼀旦传⼊的是null它就⽆法准确判断这个类型应该是什么,就有可能将类型转换错误,从⽽报错。
要解决这个问题,需要针对这些可能为空的字段,⼿动指定其转换时⽤到的类型。
⼀般情况下,我们没有必要按个字段去识别/判断它是否可以为空,⽽是将所有的字段都当做可以为空,全部⼿动设置转换类型。
[java]
1. <insert id="save"
2.        parameterType="ity.Cost">
3.        insert into cost values(
4.            val,
5.            #{name,jdbcType=VARCHAR},
6.            #{base_duration,jdbcType=INTEGER},
7.            #{base_cost,jdbcType=DOUBLE},
8.            #{unit_cost,jdbcType=DOUBLE},
9.            #{status,jdbcType=CHAR},
10.            #{descr,jdbcType=VARCHAR},
11.            #{creatime,jdbcType=TIMESTAMP},
12.            #{startime,jdbcType=TIMESTAMP},
13.            #{cost_type,jdbcType=CHAR}
14.        )
15.    </insert>
再次插⼊⼀条空数据,测试结果,能插⼊数据库。
其他数据类型参照下图表:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。