目前产品版本中Spring、MyBatis的相关版本如下所示
<spring.version>3.2.10.RELEASE</spring.version>
<mybatis-spring.version>1.1.1</mybatis-spring.version>
<mybatis.version>3.1.1</mybatis.version>
考虑到这些版本历史悠久,日志信息不全,还存在一些bug,另外这些版本也不能与Spring Boot兼容,因此考虑针对这些框架进行升级,升级后的版本如下所示
<spring.version>4.3.25.RELEASE</spring.version>
<mybatis-spring.version>1.3.2</mybatis-spring.version>
<mybatis.version>3.4.6</mybatis.version>
一旦达成以上目标之后,升级到SpringBoot就水到渠成了。比如在组件测试中就是以下的搭配。
<springframework.version>4.3.25.RELEASE</springframework.version>
<springboot.version>1.5.22.RELEASE</springboot.version>
<mybatis-spring.version>1.3.2</mybatis-spring.version>
<mybatis.version>3.4.6</mybatis.version>
这是一个大目标。在完成大目标之前,首先定一个小目标,将MyBaits版本先升级上去。通过一些处理,目前产品版本其实已经支持了新版本的mybatis了。这里主要分享一下MyBatis的升级过程中遇到的问题以及解决方案。
总的方针:兼容3.1.1和3.4.6
1. mapper格式不规范 多逗号少逗号
报错信息为:An invalid property xx was found in mapping #{
这个其实很简单,就是因为多了一个逗号,比如上图的#{begDate,,jdbcType=VARCHAR}
改为#{begDate, jdbcType=VARCHAR}
即可。这个问题在编译期就可以检查出来,不是大问题。
但是少逗号的情况,就比较麻烦了。只有运行时才会报错。
只有真实调用的时候才会报错
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'isHeightLiquidAsset jdbcType=VARCHAR' not found. Available parameters are [liquidLevel, isHeightLiquidAsset, param5, param6, updateUser, updateTime, list, setType, param3, param4, param1, param2]
at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:206)
此时MyBatis会把isHeightLiquidAsset jdbcType=VARCHAR
整体当做一个参数来解析。
在IDEA里面可以通过正则表达式来查找这种缺少逗号的xml,如下图所示(正则表达式:#\{\w+ +jdbcType=\w+\}
)
除了空格,还有更离谱的就是换行了,此时需要采用正则表达式#\{\w+\s\t\sjdbcType=\w+\}
来进行查找。
2. 类型不匹配
报错信息为:xx can not be cast to XX
主要的问题在于接口定义参数类型与xml中定义的parameterType类型不匹配导致的,修改或者去掉xml当中statement对应的parameterType属性即可。这个异常需要在第一次真实调用的时候才会报错。
3. 不存在类型转换器
出现异常Caused by: java.lang.IllegalStateException: No typehandler found for property spvId
,对应的数据库字段与POJO的属性不存在默认的typehandler,比如下面这种情况,MyBatis默认情况下是不知道如何将一个字段内容转为一个列表的。
解决方案要么是扩展一个typehandler,然后在result标签中通过typeHandler明确指定,如下所示
<result column="SPV_ID" property="spvId" typeHandler="xxxxxx"/>
要么就不要定义复杂的POJO类型,上面这个例子最后发现其实数据库里面没有这个字段,所以直接将映射关系注释了。这种异常都是在MyBatis解析初始化过程中报错的,没大问题。
4. 嵌入查询歧义resultMap
<collection property="ruleDetails"
ofType="com.xquant.trade.entity.invorder.rule.InvOrderAcceptRuleDetail"
resultMap="com.xquant.trade.dao.invorder.rule.TradeInvorderAcceptRuleDetailMapper.InvorderAcceptRuleDetailMap"
column="{ruleId=RULE_ID, version=VERSION}"
select="com.xquant.trade.dao.invorder.rule.TradeInvorderAcceptRuleDetailMapper.queryRuleDetailByRuleId">
</collection>
在上面的select
对应的语句中其实已经包含了resultMap信息(映射目标),不需要再设置了,以免冲突。