背景:
导入时涉及到保存数据到数据库,插入失败,错误如下
解决方案:
插入的实体类基本都继承了一个BaseEntity,会涉及到tmSmp和tmCreate这两个自动填充字段,tmSmp是FieldFill.INSERT类型,tmCreate是FieldFill.INSERT_UPDATE
自动填充一般流程:自行实现MetaObjectHandler并注入到IOC容器中即可
分析源码MybatisPlusAutoConfiguration#sqlSessionFactory可知
@Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { // TODO 使用 MybatisSqlSessionFactoryBean 而不是 SqlSessionFactoryBean MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(dataSource); ...... // TODO 此处必为非 NULL GlobalConfig globalConfig = this.properties.getGlobalConfig(); // TODO 注入填充器 this.getBeanThen(MetaObjectHandler.class, globalConfig::setMetaObjectHandler); // TODO 注入主键生成器 this.getBeanThen(IKeyGenerator.class, i -> globalConfig.getDbConfig().setKeyGenerator(i)); // TODO 注入sql注入器 this.getBeanThen(ISqlInjector.class, globalConfig::setSqlInjector); // TODO 注入ID生成器 this.getBeanThen(IdentifierGenerator.class, globalConfig::setIdentifierGenerator); // TODO 设置 GlobalConfig 到 MybatisSqlSessionFactoryBean factory.setGlobalConfig(globalConfig); return factory.getObject(); }
IOC容器在没有SqlSessionFactory这个bean对象时会去调用这个方法创建一个,并且注入填充器
但是由于本次的项目是多数据源,需要自行写SqlSessionFactory的返回,所以我们需要自行去注入填充器
// 设置自动填充 GlobalConfig globalConfig = this.mybatisPlusProperties.getGlobalConfig(); if (globalConfig == null) { globalConfig = GlobalConfigUtils.defaults(); } globalConfig.setMetaObjectHandler(metaObjectHandler); factory.setGlobalConfig(globalConfig);
一般流程到这里就OK了,但是每次我debug的时候都取不到MetaObjectHandler,MybatisParameterHandler#insertFill中的GlobalConfigUtils.getMetaObjectHandler(this.configuration)始终为空
最后将我的Mybatis配置类实现了SmartInitializingSingleton,在所有单例实例化结束后去重新设置一下填充器
@Override
public void afterSingletonsInstantiated() {
GlobalConfig globalConfig1 = GlobalConfigUtils.getGlobalConfig(originConfiguration2);
if (globalConfig1 != null) {
globalConfig1.setMetaObjectHandler(metaObjectHandler);
}
}
完美解决问题,最终找到罪魁祸首
在我定义SqlSessionFactory时有一段代码如下
MybatisConfiguration originConfiguration = this.mybatisPlusProperties.getConfiguration(); MybatisConfiguration configuration = new MybatisConfiguration(); if (originConfiguration != null) { BeanUtils.copyProperties(originConfiguration, configuration); }
这个工具类copy的时候会调用到两个弃用的方法,会调用MybatisConfiguration两个弃用的方法getGlobalConfig和setGlobalConfig
因此需要将copy的代码改成
BeanUtils.copyProperties(originConfiguration, configuration, "globalConfig");
即可
最后望大家写代码细心,少出bug(#^.^#)
标签:填充,MetaObjectHandler,factory,生效,globalConfig,TODO,注入 From: https://www.cnblogs.com/lhbilibili/p/18075301