Bootstrap

mybatis-plus框架TABLE_INFO_CACHE获取不到对应的TableInfo对象

问题场景

自己搭建了一套SpringBoot项目,在后期的开发中,欲将mybatis平滑升级为mybatis-plus升,基本升级完毕,在调用IService的saveOrUpdateBatch进行批量新增记录或者更新记录的时候遇到了问题"error: can not execute. because can not find cache of TableInfo for entity!",进行代码追踪如下:

 public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
        Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
        String keyProperty = tableInfo.getKeyProperty();
        Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
        return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
            Object idVal = ReflectionKit.getFieldValue(entity, keyProperty);
            return StringUtils.checkValNull(idVal) || CollectionUtils.isEmpty(sqlSession.selectList(this.getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
        }, (sqlSession, entity) -> {
            MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap();
            param.put("et", entity);
            sqlSession.update(this.getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
        });
    }

进入方法获取TableInfo对象:

TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);

我们会看到如下代码:

public static TableInfo getTableInfo(Class<?> clazz) {
        if (clazz != null && !ReflectionKit.isPrimitiveOrWrapper(clazz) && clazz != String.class && !clazz.isInterface()) {
            Class<?> targetClass = ClassUtils.getUserClass(clazz);
            TableInfo tableInfo = (TableInfo)TABLE_INFO_CACHE.get(targetClass);
            if (null != tableInfo) {
                return tableInfo;
            } else {
                for(Class<?> currentClass = clazz; null == tableInfo && Object.class != currentClass; tableInfo = (TableInfo)TABLE_INFO_CACHE.get(ClassUtils.getUserClass(currentClass))) {
                    currentClass = currentClass.getSuperclass();
                }

                if (tableInfo != null) {
                    TABLE_INFO_CACHE.put(targetClass, tableInfo);
                }

                return tableInfo;
            }
        } else {
            return null;
        }
    }

问题代码行:

 TableInfo tableInfo = (TableInfo)TABLE_INFO_CACHE.get(targetClass);

现在我的mybatis升级为mybatis-plus的操作以及相关解决方案分享如下:

依赖包替换

将pom文件中原来mybatis依赖替换为baomidou的mybatis-plus依赖:

<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>

这里有一个小坑,就是mybatis-puls的版本问题,如果小伙伴们不注意,运气不好,会遇到版本不匹配问题,我是完美的跳坑了。我是有一个相迫症是一切从新a,就想用最新的,最后还是败给了版本。

mybatisPlusConfig配置文件修改

依赖包替换并更新依赖后,就该修改配置文件了,将MyBatisConfig配置文件中的@Bean注释掉,当然,这里却决于你,你也可以直接在在原来的配置上做修改,我新建一个新的类MyBatisPlusConfig,所以呢将原来的@Bean注解注释掉让其配置不生效就好了。
在这里插入图片描述
MyBatisPlusConfig中的配置文件:

 @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        String typeAliasesPackage = env.getProperty("mybatis-plus.typeAliasesPackage");
        String mapperLocations = env.getProperty("mybatis-plus.mapperLocations");
        String configLocation = env.getProperty("mybatis-plus.configLocation");
        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
        VFS.addImplClass(SpringBootVFS.class);

        final MybatisSqlSessionFactoryBean  sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
        sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
        return sessionFactory.getObject();
    }

将SpringBootVFS,MybatisSqlSessionFactoryBean群不替换为baomidou包想的相应文件。yml的配置文件做相应的修改即可。

报错原因

万恶之源在这里,MyBatis-Plus应该使用MybatisSqlSessionFactoryBean 而不是 SqlSessionFactoryBean。MybatisPlusAutoConfiguration的源码中,如果已经有配置SqlSessionFactory。MyBatis-Plus将不会自动帮我们注入SqlSessionFactory,而使用我们自己定义的SqlSessionFactory。而我当时是没有替换掉mybatis的SqlSessionFactoryBean,在MyBatisPlusConfig里还是用的

import org.mybatis.spring.SqlSessionFactoryBean;

所以,mybatis-plus中TableInfoHelper的TABLE_INFO_CACHE根据字节码对象获取不到对应的TableInfo对象。
解决方案就相应的接知道了撒:
直接替换掉SqlSessionFactoryBean,换位MybatisSqlSessionFactoryBean就可以了。

补充

在入坑之后呢,我查阅相关资料,发现其他大佬也有遇到相关问题,但是原因和解决方案都是不一样的,这里附上链接,可参考:
https://blog.csdn.net/weixin_43401380/article/details/108863687

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;