问题场景:
项目中有使用mybatis-plus的逻辑删除插件,在项目初始化时有加载此插件,由于近期mybatis-plus版本升级从3.0-gama升级到3.2.0版本,在原本的逻辑删除处出现报错:
Caused by: java.lang.AbstractMethodError: com.baomidou.mybatisplus.core.injector.AbstractSqlInjector.getMethodList(Ljava/lang/Class;)Ljava/util/List;
at com.baomidou.mybatisplus.core.injector.AbstractSqlInjector.inspectInject(AbstractSqlInjector.java:51)
at com.baomidou.mybatisplus.core.MybatisMapperAnnotationBuilder.parse(MybatisMapperAnnotationBuilder.java:122)
at com.baomidou.mybatisplus.core.MybatisMapperRegistry.addMapper(MybatisMapperRegistry.java:82)
at com.baomidou.mybatisplus.core.MybatisConfiguration.addMapper(MybatisConfiguration.java:104)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.bindMapperForNamespace(XMLMapperBuilder.java:436)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:96)
at com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean.buildSqlSessionFactory(MybatisSqlSessionFactoryBean.java:589)
at com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean.afterPropertiesSet(MybatisSqlSessionFactoryBean.java:426)
at com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean.getObject(MybatisSqlSessionFactoryBean.java:624)
at com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration.sqlSessionFactory(MybatisPlusAutoConfiguration.java:222)
at com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration$$EnhancerBySpringCGLIB$$61a6a33a.CGLIB$sqlSessionFactory$2(<generated>)
at com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration$$EnhancerBySpringCGLIB$$61a6a33a$$FastClassBySpringCGLIB$$b96c134.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
at com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration$$EnhancerBySpringCGLIB$$61a6a33a.sqlSessionFactory(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 107 common frames omitted
问题分析
1.由此报错可以可以看出时一个方法错误,具体的方法是:AbstractSqlInjector.getMethodList(Ljava/lang/Class;)方法
2.进入AbstractSqlInjector(mybatis-plus版本3.2.0)类进行查看,此处的方法为
public abstract List<AbstractMethod> getMethodList(Class<?> mapperClass);
3.进入老的版本查看AbstractSqlInjector(mybatis-plus版本3.0-gama)类进行查看,此处的方法为
public abstract List<AbstractMethod> getMethodList();
问题处理
在项目中的MybatisConfig中修改方法,原来的逻辑删除加载为
@Bean
public ISqlInjector sqlInjector() {
ISqlInjector sqlInjector = new LogicDeleteInjector();
log.info("sqlInjector init");
return sqlInjector;
}
老版本的LogicDeleteInjector类是这样的
public class LogicDeleteInjector extends AbstractSqlInjector {
public LogicDeleteInjector() {
}
public List<AbstractMethod> getMethodList() {
return (List)Stream.of(new Insert(), new LogicDelete(), new LogicDeleteByMap(), new LogicDeleteById(), new LogicDeleteBatchByIds(), new LogicUpdate(), new LogicUpdateById(), new LogicSelectById(), new LogicSelectBatchByIds(), new LogicSelectByMap(), new LogicSelectOne(), new LogicSelectCount(), new LogicSelectMaps(), new LogicSelectMapsPage(), new LogicSelectObjs(), new LogicSelectList(), new LogicSelectPage()).collect(Collectors.toList());
}
}
这里可以看到getMethodList方法是没有入参的,此处添加入参将其修改为:
public class LogicDeleteInjector extends AbstractSqlInjector {
public LogicDeleteInjector () {
}
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
return (List)Stream.of(new Insert(), new LogicDelete(), new LogicDeleteByMap(), new LogicDeleteById(), new LogicDeleteBatchByIds(), new LogicUpdate(), new LogicUpdateById(), new LogicSelectById(), new LogicSelectBatchByIds(), new LogicSelectByMap(), new LogicSelectOne(), new LogicSelectCount(), new LogicSelectMaps(), new LogicSelectMapsPage(), new LogicSelectObjs(), new LogicSelectList(), new LogicSelectPage()).collect(Collectors.toList());
}
}
问题反思
按照正常的升级流程,此处如果统一使用LogicDeleteInjector进行初始化,代码在编译时就会报错。
但是老版本中我们的架构对逻辑删除的组件做了一次封装,我们的逻辑删除都是走LogicDeleteInjector类进行插件初始化,在框架升级后老的LogicDeleteInjector没有删除而是新增了一个实现XXXLogicDeleteInjector使用新的方式进行初始化,所以导致此问题在编译时是通过的,因为老的类中的方法是没问题的,但是在运行时整体运行的是新版本,新版本中LogicDeleteInjector的父类AbstractSqlInjector中的getMethodList方法已经发生变动,所以报出以上错误