MetaObjectHandler自动填充不生效
背景:
导入时涉及到保存数据到数据库,插入失败,错误如下
解决方案:
插入的实体类基本都继承了一个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(#^.^#)
分类:
springLearn
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端