查回来的数据除了 id,其他字段都是 null
数据结构不完整:您收到的历史对话和知识库文件数据中,几乎所有重要的字段(除了id和title)都是null,包括userId、createdTime等关键字段。这会导致前端无法根据创建时间来正确分类显示(今天、7天内、更早)。
我后面改的 MyBatisPlusConfig,破坏了原本 MyBatis-Plus 的
自动XML绑定
机制,导致 Mapper 接口找不到对应的 XML,虽然查询了,但是实体类字段无法正确赋值,最终查回来的数据除了 id,其他字段都是null
!
接下来完整分析原因,让你一次搞懂。✅
📍先看【两版配置】的本质区别
✅ 原来能用的配置(正常版)
@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() { ... }@Beanpublic PageInterceptor pageInterceptor() { ... }@Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration -> {configuration.setMapUnderscoreToCamelCase(true);configuration.getTypeHandlerRegistry().register(TimestampToLongTypeHandler.class);};}
}
特点:
-
只做了小幅度配置 ✅
-
没有自己创建
SqlSessionFactory
(MyBatis-Plus 自动管理的)✅ -
XML文件、Mapper接口、实体类都是自动绑定的 ✅
-
保持了 SpringBoot + Mybatis-Plus 最佳兼容性 ✅
❌ 后来改的配置(出错版)
@Configuration
@MapperScan("com.example.chat2.mapper")
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() { ... }@Beanpublic PageInterceptor pageInterceptor() { ... }@Beanpublic ConfigurationCustomizer configurationCustomizer() { // 多注册了很多 TypeHandler }@Bean@Primarypublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));return factoryBean.getObject();}
}
特点:
-
自己强制 new 了一个
SqlSessionFactoryBean
❌ -
手动指定了
mapper/*.xml
,但 破坏了 MyBatis-Plus 的自动扫描机制 ❌ -
导致 Mapper 接口和XML没有正确绑定 ❌
-
实际上运行时,Mapper接口的SQL找不到对应的XML解析结果,最后只能返回默认值(id 可能是接口返回的默认值,其他字段全是 null)❌
-
TypeHandlerRegistry
注册太早,生效顺序也可能乱了 ❌
📍所以问题根本原因是:
问题点 | 影响 |
---|---|
你自己 new 了一个新的 SqlSessionFactoryBean | 打断了 MyBatis-Plus 自带的配置和自动扫描 |
factoryBean.setMapperLocations 指定得太死 | 只扫 mapper/*.xml ,如果有子目录,比如 mapper/chat/xxx.xml 根本扫不到 |
mapper 接口找不到 XML | Mybatis执行SQL时,XML定义的SQL读不到,映射结果自然是null |
📍为什么改回旧版就可以了?
因为之前的旧版配置:
-
完全让 Mybatis-Plus 自动管理生命周期(没有破坏它的 SqlSessionFactory)
-
自动扫描所有 Mapper 和 XML
-
自动使用
mapUnderscoreToCamelCase = true
-
自动做了 ResultMap 和实体类映射
所以即使数据库字段有值,自动都能注入到对象里。🌟
而你新改的版本,强行覆盖了 SpringBoot 和 MyBatis-Plus的默认配置,所以崩了。
📍正确的做法应该是:
✅ 保持 MyBatisPlusConfig
不要自己 new SqlSessionFactory
。
✅ 如果要加自己的 TypeHandler,只需要在 ConfigurationCustomizer
里注册,不需要自己重新建 SqlSessionFactory!
✅ 保证配置最小化,尊重 MyBatis-Plus 自动配置的体系。
📍总结你的问题链条
自己新建SqlSessionFactory ➡ 破坏MyBatis-Plus默认行为 ➡ Mapper接口找不到XML ➡ 查询回来的实体字段全部是null
所以回到最原始干净的MyBatisPlusConfig,系统就恢复正常了!✅
📍额外给你优化一下,推荐你最标准的【新版MyBatisPlusConfig】
package com.example.chat2.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.example.chat2.handler.EnumTypeHandler;
import com.example.chat2.handler.JsonListTypeHandler;
import com.example.chat2.handler.JsonMapTypeHandler;
import com.github.pagehelper.PageInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.List;
import java.util.Map;
import java.util.Properties;@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}@Beanpublic PageInterceptor pageInterceptor() {PageInterceptor pageInterceptor = new PageInterceptor();Properties properties = new Properties();properties.setProperty("helperDialect", "mysql");pageInterceptor.setProperties(properties);return pageInterceptor;}@Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration -> {configuration.setMapUnderscoreToCamelCase(true);configuration.getTypeHandlerRegistry().register(List.class, JsonListTypeHandler.class);configuration.getTypeHandlerRegistry().register(Map.class, JsonMapTypeHandler.class);configuration.getTypeHandlerRegistry().register(TimestampToLongTypeHandler.class);configuration.getTypeHandlerRegistry().register(Enum.class, EnumTypeHandler.class);};}
}
🔵 注意:完全没有自己建 SqlSessionFactory,只保留插件、类型处理器、驼峰映射!
📍最终结论
✅ 你改回了之前的简洁配置,是正确的!
✅ 不要自己 new SqlSessionFactoryBean
,不然必出问题。 ✅ 如果要扩展,只能在 ConfigurationCustomizer
里扩展,不能动核心生命周期。
要不要我顺便帮你出一版 "判断系统 Mapper 是否加载正确的检测代码"?(可以防止以后出这种问题,一眼定位到)
要的话告诉我,我可以直接写一版给你~很实用!🚀
要继续吗?
分析完两个配置类的区别和出现问题的原因:
- 问题根本原因:SqlSessionFactory覆盖
- 后一个配置类中手动创建了SqlSessionFactory Bean并标记为@Primary
- 这个新的工厂覆盖了Spring Boot的自动配置的工厂
- 新工厂虽然设置了XML位置,但缺少了其他重要配置
- 关键差异点:
- 原配置:只提供ConfigurationCustomizer让Spring自动配置使用
- 新配置:完全覆盖SqlSessionFactory,导致部分配置丢失
- 具体配置丢失:
- 在新配置中,factoryBean.setConfiguration没有被设置
- 创建了SqlSessionFactory但没有应用之前的configurationCustomizer
- 驼峰映射配置可能没有被正确应用到新工厂
- 解决问题的正确方法:
- 方案1:使用原来的配置方式,让Spring Boot管理SqlSessionFactory
- 方案2:如果需要自定义SqlSessionFactory,确保完整应用所有配置:
java
Apply to JacksonConfi...
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
// 注册所有类型处理器
factoryBean.setConfiguration(configuration);
驼峰命名转换是关键配置,不正确设置会导致exactly你看到的问题:只有id和title映射正确(可能因为命名相同),其他下划线命名的字段全是null。