文中,mybatis-plus 用 mp表示
背景:
mp2.1.8版本 升级 mp版本到3.5.6,为了支持租户功能。
问题:
做数据查询时:
传入 page和vm(自定义入参对象) 去执行xxxmapper.xml的sql。
vm中有字段name。mapper.xml中使用占位符#{name}做查询。
在2.1.8版本,执行正常。 但是升级到3.5.6版本后报错。
报错:
排查思路:
首先网上找处理方案,发现基本都是把 #{name} 改成 #{vm.name},把对象名传入。
但是按老版本的·逻辑,page不会识别认为是一个参数,vm应该是单参数,内部的字段应该是会解析,字段名应该做为key,#{name}应该能获取到这个参数。
结合报错堆栈,在mp3.5.6的版本调试
入参解析代码:
在ParamNameResolver.getNamedParams 方法去解析参数时,如果只要一个对象,如果是集合会转map,不然直接返回的这个对象。
当多个是把对象名和parm1parm2当key。这里把page也当作是一个对象参数,所以是多参数。
注意:有注解Param("vm")的话,也会按多参数的逻辑,把vm对象塞入解析出来的Paramter map中。
mybatisplus的多入参sql执行时:
入口:
MybatisMapperMethod.execute(sqlsession args)
分派不同的sql执行方法:
MybatisMapperMethod.executeForMany(sqlsession,args)
sqlsession.select执行sql之前:
先校验sql中的参数,如果xml#{name}没有这个参数就直接报错
再执行 拦截器 PaginationInnerInterceptor.beforeQuery,从Paramter map中 获取 page参数。
所以page这个参数没办法通过 简单的修改 ParamNameResolver.getNamedParams,把他去掉,后面都需要用page这个参数。
总结
最后处理方案还是 修改原来的xml,参数占位符带上对象名,如 用 #{vm.name} 代替#{name}。 更符合规范。
不建议修改源码,应该与时俱进用新规范 新包。 修改一些开源项目,这些项目很可能自带技术债。以后升级还是会留坑。
其他注意点
还有个注意点,如果表字段用了 limit这种这种关键字,在3.5.6这个版本也 需要加`` 标识,如:@TableFiled("`limit`")