1. 问题现象与背景定位
最近在整合Spring Boot与MyBatis-Plus时,控制台突然抛出这个典型的Bean创建异常:
code复制org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]
这个报错表面看是Spring容器无法创建sqlSessionFactory这个核心Bean,但背后可能隐藏着多种配置问题。结合当前技术栈和报错上下文,我们需要先明确几个关键点:
- MyBatis-Plus的自动配置机制:MyBatis-Plus通过
MybatisPlusAutoConfiguration类实现自动配置,其中sqlSessionFactory的创建依赖于数据源、MyBatis配置等前置条件 - Spring Bean的生命周期:当Spring尝试创建Bean时,如果依赖的其他Bean未就绪或配置有误,就会抛出此类异常
- 典型触发场景:根据社区常见案例,这类问题多发生在多数据源配置冲突、依赖版本不兼容或XML映射文件缺失等场景
关键提示:遇到此类问题时,首先要查看完整异常堆栈的"Caused by"部分,那里往往藏着真正的根因。单纯看最外层报错信息容易误判问题方向。
2. 完整排查链路与诊断方法
2.1 查看完整异常堆栈
在IDEA中展开异常堆栈,重点关注第一个"Caused by"部分。常见的情况包括:
-
数据源问题:
code复制Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available这表明数据源未正确配置
-
Mapper扫描问题:
code复制Caused by: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.example.mapper.UserMapper.selectById这通常说明Mapper接口与XML文件未正确映射
-
版本冲突:
code复制java.lang.NoSuchMethodError: org.mybatis.spring.SqlSessionFactoryBean.setConfiguration(Lorg/apache/ibatis/session/Configuration;)这提示可能存在MyBatis与MyBatis-Plus版本不兼容
2.2 检查依赖树
执行mvn dependency:tree或gradle dependencies,查看关键依赖版本:
- MyBatis-Plus版本(建议3.5.3+)
- MyBatis版本(需与MyBatis-Plus匹配)
- Spring Boot Starter版本
- 数据库驱动版本
典型版本冲突案例:
xml复制<!-- 错误示例:同时引入mybatis和mybatis-plus的spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
2.3 配置检查清单
-
application.yml关键配置:
yaml复制mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启SQL日志 mapper-locations: classpath*:/mapper/**/*.xml # XML映射文件位置 -
数据源配置验证:
- 检查
spring.datasource.url格式是否正确 - 测试数据库连接是否通畅
- 多数据源场景下是否添加了
@Primary注解
- 检查
-
Mapper接口扫描:
java复制@MapperScan("com.example.mapper") // 确保包路径正确 @SpringBootApplication public class Application { ... }
3. 高频问题解决方案
3.1 多数据源配置冲突
当项目中使用多个数据源时,如果没有正确配置,会导致sqlSessionFactory创建失败。正确做法:
- 主数据源配置:
java复制@Primary
@Bean("primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
- 次数据源配置:
java复制@Bean("secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
- 对应的MyBatis配置:
java复制@Primary
@Bean("primarySqlSessionFactory")
public SqlSessionFactory primarySqlSessionFactory(
@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setMapperLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/primary/*.xml"));
return sessionFactory.getObject();
}
3.2 XML映射文件缺失
当Mapper接口存在但对应的XML文件缺失或路径不正确时,会出现绑定异常。解决方案:
- 确认
mybatis-plus.mapper-locations配置的路径 - 检查XML文件中的namespace是否与Mapper接口全限定名一致
- 示例XML文件位置:
code复制src/main/resources
└── mapper
└── user
└── UserMapper.xml
对应的配置应为:
yaml复制mybatis-plus:
mapper-locations: classpath:mapper/**/*.xml
3.3 分页插件未配置
使用MyBatis-Plus的分页功能时,如果忘记配置分页插件,可能导致特殊场景下的Bean创建异常:
java复制@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
4. 高级调试技巧
4.1 启用MyBatis-Plus完整日志
在application.yml中添加:
yaml复制logging:
level:
com.baomidou.mybatisplus: DEBUG
org.mybatis.spring: DEBUG
这可以输出以下关键信息:
- 实际加载的XML映射文件列表
- 最终生效的MyBatis配置项
- SQL语句执行过程
4.2 使用Arthas动态诊断
对于生产环境问题,可以使用Arthas工具进行在线诊断:
bash复制# 查看Bean创建过程
watch org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory createBean '{params, throwExp}'
# 检查sqlSessionFactory的属性
getstatic com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration sqlSessionFactory
4.3 自定义Bean初始化检查
创建一个配置类来验证关键Bean:
java复制@Configuration
public class MyBatisHealthCheck {
@Autowired
private SqlSessionFactory sqlSessionFactory;
@PostConstruct
public void checkConfiguration() {
Configuration configuration = sqlSessionFactory.getConfiguration();
log.info("Loaded mappers: {}", configuration.getMapperRegistry().getMappers());
log.info("Loaded type handlers: {}", configuration.getTypeHandlerRegistry().getTypeHandlers());
}
}
5. 版本兼容性矩阵
根据MyBatis-Plus官方文档和社区实践,以下是经过验证的稳定版本组合:
| MyBatis-Plus | MyBatis | Spring Boot | JDK | 备注 |
|---|---|---|---|---|
| 3.5.3.1 | 3.5.13 | 2.7.12 | 8-17 | 当前推荐生产版本 |
| 3.5.2 | 3.5.11 | 2.6.11 | 8-17 | |
| 3.4.3.4 | 3.5.10 | 2.5.14 | 8-15 | 老项目维护版本 |
| 3.5.7 | 3.5.13 | 3.0.0 | 17+ | Spring Boot 3.x专用版本 |
特别注意:MyBatis-Plus 3.5.7+版本开始支持Spring Boot 3.x,但需要JDK17+环境。如果项目使用Spring Boot 2.x,建议选择3.5.3.x版本。
6. 典型错误配置示例
6.1 循环依赖问题
错误场景:
java复制@Bean
public ServiceA serviceA(ServiceB serviceB) { ... }
@Bean
public ServiceB serviceB(ServiceA serviceA) { ... }
@Bean
public SqlSessionFactory sqlSessionFactory(ServiceA serviceA) { ... }
解决方案:
- 使用
@Lazy注解打破循环 - 重构代码结构,避免循环依赖
- 最佳实践是将MyBatis相关Bean单独配置
6.2 属性注入失败
错误配置:
yaml复制mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 错误:应为mapUnderscoreToCamelCase
正确配置:
yaml复制mybatis-plus:
configuration:
mapUnderscoreToCamelCase: true
6.3 达梦数据库特殊配置
对于达梦数据库,需要额外配置:
java复制@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.DM));
return interceptor;
}
同时在数据源配置中指定方言:
yaml复制spring:
datasource:
driver-class-name: dm.jdbc.driver.DmDriver
url: jdbc:dm://localhost:5236/SAMPLE
7. 性能优化建议
7.1 批量操作优化
使用MyBatis-Plus的批量操作方法:
java复制// 传统方式:性能差
for (User user : userList) {
userMapper.insert(user);
}
// 优化方式:使用Service的saveBatch方法
userService.saveBatch(userList, 1000); // 每批1000条
7.2 二级缓存配置
在配置类中添加:
java复制@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new CachingInnerInterceptor());
return interceptor;
}
在Mapper接口上添加注解:
java复制@CacheNamespace(implementation = MybatisRedisCache.class, eviction = MybatisRedisCache.class)
public interface UserMapper extends BaseMapper<User> {}
7.3 SQL注入器扩展
自定义SQL方法:
java复制public class CustomSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new InsertBatchSomeColumn());
return methodList;
}
}
注册到Spring容器:
java复制@Bean
public CustomSqlInjector customSqlInjector() {
return new CustomSqlInjector();
}
8. 生产环境注意事项
-
连接池监控:建议集成Druid连接池并开启监控
java复制@Bean @ConfigurationProperties("spring.datasource.druid") public DataSource dataSource() { return DruidDataSourceBuilder.create().build(); } -
慢SQL监控:配置慢SQL阈值
yaml复制mybatis-plus: configuration: log-slow-sql: true slow-sql-millis: 1000 -
多租户方案:使用MyBatis-Plus的多租户插件
java复制@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() { @Override public String getTenantIdColumn() { return "tenant_id"; } @Override public Expression getTenantId() { return new StringValue("当前租户ID"); } })); return interceptor; } -
SQL防注入:禁止使用
${}进行字符串拼接,所有动态参数必须使用#{}
在实际项目中,遇到sqlSessionFactory创建失败的问题时,建议按照本文的排查链路逐步验证。从我的经验来看,90%的问题都出在依赖版本冲突或基础配置错误上。特别是在微服务架构中,当组件版本跨度较大时,更需要仔细检查依赖关系。
