Spring Boot+MyBatis-Plus报错:Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required 排查与修复

发布时间:2026/10/15 6:35:28
Spring Boot+MyBatis-Plus报错:Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required 排查与修复
1. 报错现场先看懂异常信息再说搞 Spring Boot 的人十有八九都在启动日志里撞到过这句话Property sqlSessionFactory or sqlSessionTemplate are required第一次看到这个报错我的第一反应是我的 MyBatis 配置丢了还是 Mapper 没扫到后来排查多了才发现这句异常背后往往不是某个依赖没加而是 Spring 容器压根没有把SqlSessionFactory或SqlSessionTemplate初始化出来或者初始化到一半被某些配置打断了。先说这个异常的典型出现位置。最常见的是项目启动阶段Spring 在创建 Mapper 代理对象时抛出的。报错栈一般长这样org.springframework.beans.factory.BeanCreationException: Error creating bean with name xxxMapper defined in file [...] ... Caused by: java.lang.IllegalArgumentException: Property sqlSessionFactory or sqlSessionTemplate are required at org.mybatis.spring.support.SqlSessionDaoSupport.checkDaoConfig(SqlSessionDaoSupport.java:50) at org.mybatis.spring.mapper.MapperFactoryBean.checkDaoConfig(MapperFactoryBean.java:75)关键点就在MapperFactoryBean.checkDaoConfig这一行。Spring 想要创建 Mapper 接口的代理对象需要往MapperFactoryBean里塞一个SqlSessionFactory或者SqlSessionTemplate结果发现两个都是 null直接抛异常终止启动。那问题就来了为什么我明明加了mybatis-plus-boot-starter也写了MapperScan它还是找不到这个报错到底怪谁我建议你先把报错当线索而不是结论接着往下看根因。2. 根因拆解为什么 Spring 容器里就是找不到 sqlSessionFactory2.1 自动装配机制到底干了什么先说 MyBatis-Plus 的自动装配逻辑。当你引入mybatis-plus-boot-starter后Spring Boot 启动时会通过MybatisPlusAutoConfiguration这个自动配置类来装配核心对象。它内部会做几件关键的事如果容器里没有SqlSessionFactory就创建一个MybatisSqlSessionFactoryBean来构建。注意这是 MyBatis-Plus 自己的实现类不是 MyBatis 官方那个SqlSessionFactoryBean。把SqlSessionTemplate也初始化好等待被注入到 Mapper。然后 Mapper 接口通过MapperScan被扫描注册每个 Mapper 对应一个MapperFactoryBean它在初始化时从容器里拿SqlSessionFactory来设置。这整个链路只要断掉一环MapperFactoryBean拿不到核心对象就会报你看到的那句错。换句话说异常只是结果链路断了才是原因。2.2 三个最容易被忽略的失效点我把自己踩过的坑以及帮别人排查时见到的案例整理了一下最容易出问题的是这三个第一个自动配置被整体排除掉了。有些项目早期为了调试写过类似这样的代码SpringBootApplication(exclude {MybatisPlusAutoConfiguration.class})结果后来代码忘了删或者提交代码时不小心把排除项带进了生产分支。一旦排除了自动配置类容器里就不会有SqlSessionFactory所有 Mapper 全部初始化失败。排查的时候如果不仔细看启动类上的注解光加 Mapper 注解、加依赖都没用。第二个依赖冲突导致自动配置类根本没生效。比如项目里同时引入了 MyBatis 官方的mybatis-spring-boot-starter和 MyBatis-Plus 的mybatis-plus-boot-starter。两个 starter 都试图做自动装配谁先加载、谁后加载、装配逻辑互相覆盖经常出现SqlSessionFactory被创建成普通对象、MyBatis-Plus 的功能失效的情况。更直观的现象是启动不报错但等 MyBatis-Plus 的分页插件、逻辑删除生效时怎么调都不起作用。第三个自定义配置类覆盖了SqlSessionFactory。有些团队会自己写一个配置类手动定义SqlSessionFactory的 Bean可能是为了加插件、做拦截器、配置驼峰映射等等。如果这个自定义 Bean 写得不完整比如自己 new 了一个SqlSessionFactoryBean但并没有调用afterPropertiesSet()去真正构建或者漏设置数据源那容器里确实有一个名为sqlSessionFactory的 Bean但它内部没有真正的会话工厂能力。更麻烦的是MyBatis-Plus 的自动装配规则是“容器里如果有则不覆盖”你的残缺 Bean 直接霸占了位置后续所有 Mapper 都会拿到坏对象。你可能要问为什么 MyBatis-Plus 要设计成“容器里有就不创建”因为这是 Spring Boot 自动配置的一贯约定叫做 ConditionalOnMissingBean意思是没有你自己定义的 Bean我才上手干活。这个约定本身没毛病但它也让你自己写坏一个 Bean这件事变得特别隐蔽。3. 修复方案四种落地做法从快到稳3.1 方案一核对依赖与版本如果是新项目或者刚升级了 Spring Boot / MyBatis-Plus 版本先看一眼依赖长什么样。我一般推荐这种标准组合dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency然后确定项目里没有重复引入 MyBatis 相关的 starter。用 Maven 依赖树检查一下最直接mvn dependency:tree -Dincludesorg.mybatis:*,org.mybatis.spring:*,com.baomidou:*正常的树里应该以 MyBatis-Plus 自家的包为主关联依赖如mybatis-spring、mybatis会作为传递依赖出现。如果发现同时存在mybatis-plus和mybatis-spring-boot-starter大概率就是冲突源。3.2 方案二恢复自动配置清理 exclude如果你排查后发现启动类上有排除自动配置的注解直接删掉即可。有些项目还习惯用spring.autoconfigure.exclude配置项排除自动配置类这在application.yml里长这样spring: autoconfigure: exclude: - com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration有这个配置的注释掉或删掉重启验证。还有一点需要留意有的人会为了只启动部分自动配置故意排除一批类例如配合 JPA 或其他 ORM 共存时。如果你确实需要多 ORM 共存不建议靠排除 MyBatis-Plus 自动配置来实现更好的做法是给不同 Mapper 包分别建立独立的SqlSessionFactory和SqlSessionTemplate指向不同数据源。这样既不破坏 MyBatis-Plus 装配又能隔离两套数据库操作后续排查也省心。3.3 方案三手动提供 SqlSessionFactory 的兜底 Bean如果自动配置确实没法用——比如你不小心写了残缺的SqlSessionFactory又或者数据源是动态多数据源、需要自己接管链路——那就自己补一个完整的MybatisSqlSessionFactoryBean。下面这个配置是我常用的完整形态Configuration public class MybatisPlusConfig { Bean public MybatisSqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) { MybatisSqlSessionFactoryBean factoryBean new MybatisSqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); // 指定 XML 映射文件的位置如果不指定注解 Mapper 能扫到 // 但 XML 里的 SQL 会被悄悄忽略 factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(classpath*:mapper/**/*.xml)); // 设置全局配置 MybatisConfiguration configuration new MybatisConfiguration(); configuration.setMapUnderscoreToCamelCase(true); configuration.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class); factoryBean.setConfiguration(configuration); // 数据库策略id 自增、逻辑删除字段等都可以在全局配 GlobalConfig globalConfig new GlobalConfig(); GlobalConfig.DbConfig dbConfig new GlobalConfig.DbConfig(); dbConfig.setIdType(IdType.AUTO); dbConfig.setLogicDeleteField(deleted); globalConfig.setDbConfig(dbConfig); factoryBean.setGlobalConfig(globalConfig); return factoryBean; } Bean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }手动装配时要注意几个细节MybatisSqlSessionFactoryBean是 MyBatis-Plus 提供的类别拿成 MyBatis 官方的SqlSessionFactoryBean否则 MyBatis-Plus 的GlobalConfig、逻辑删除、分页插件一概不生效。如果没设置 mapperLocationsXML 里的 SQL 不会被加载报错可能是Invalid bound statement这种问题启动时不报错等调用方法时才报更难缠。如果项目配置了多个数据源DataSource必须明确指定Spring 注入的是容器里的主数据源。要是主数据源标注错了SqlSessionFactory 指向了一个没连通的库依然会出各种连带问题。3.4 方案四检查与官方 MyBatis starter 的冲突实际项目中最让我花时间的其实是依赖冲突。很多人代码里看着什么都对启动类也没 exclude配置类也干净可就是报这个错。后来才发现pom.xml里同时引了 MyBatis 官方 starter 和 MyBatis-Plus starter。这两种 starter 同时存在的杀伤力在于它们都会对SqlSessionFactory做条件装配而且装配顺序不固定。我在某个项目里实际经历过代码正常启动但 MyBatis-Plus 的IService系列接口调用时总是报找不到SqlSessionTemplate。后来在依赖树里看到mybatis-spring-boot-starter和mybatis-plus-boot-starter同时存在把官方的 starter 排除掉后一切恢复正常。排除方式dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version exclusions exclusion groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId /exclusion /exclusions /dependency实话讲我见过不少项目就是因为引了别人封装好的通用依赖或者同事在协作时顺手加了一个官方 mybatis starter导致 MyBatis-Plus 的自动配置时灵时不灵。遇到sqlSessionFactory报错先看依赖树成本最低收益最大。4. 排查方法论从报错栈一步步逆推4.1 用 --debug 看自动配置报告光知道修复方案还不够真要排查起来还得有一套方法。我最常用的第一板斧是看自动配置报告。Spring Boot 启动时加一个--debug参数或者直接在配置里把debug打开控制台会打印一份CONDITIONS EVALUATION REPORT里面会列出每个自动配置类匹配成功还是匹配失败以及具体原因。比如看到这种一行MybatisPlusAutoConfiguration: Did not match: - ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) did not find any beans那问题就是数据源没有初始化SqlSessionFactory 当然也就构建不了。顺着这行记录去查数据源十拿九稳。如果报告里连MybatisPlusAutoConfiguration都没出现说明自动配置类压根没被加载那大概率是排除配置或者依赖缺失。4.2 检查 MapperScan 与 Mapper 接口注册有时候报错并不是SqlSessionFactory不存在而是 Mapper 接口扫描注册的时机早于SqlSessionFactory的创建。这种情况在 Spring Boot 低版本 多模块项目中偶发。MapperScan如果是写在某个配置类上的而这个配置类在ComponentScan扫描之外或者扫描路径配置有误就会导致 Mapper 没有被注册此时启动时通常不会直接报sqlSessionFactory错而是报没有找到名为 xxxMapper 的 Bean。但如果你同时把MapperScan写到了多个地方且其中一个扫描到了另一个模块的 Mapper而那个模块没被正确纳入装配也可能触发这个异常。我建议的检查方式是在启动类上明确标注扫描包SpringBootApplication MapperScan(com.example.project.mapper) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }这样最不容易出错。也可以选择在每个 Mapper 接口上加Mapper注解两条路选一条就行别混用让扫描重复。4.3 检查自定义配置类是否破坏装配链路排查到最后一步也是最多人忽略的就是自己写的配置类。我见过一个案例某团队在配置类里加了Bean返回类型写的是SqlSessionFactory返回值却是一个new SqlSessionFactoryBean()而且没有调用getObject()。于是 Spring 容器里确实注册了一个 Bean名字也叫sqlSessionFactory但类型是SqlSessionFactoryBean而不是SqlSessionFactory。后面MapperFactoryBean按类型找SqlSessionFactory时发现没有匹配的 bean报错信息还是一样。如果你怀疑是自定义配置的问题最快的验证办法是临时把配置类上相关的Bean方法注解全部注释掉让 MyBatis-Plus 的默认装配接管。如果项目恢复正常启动就说明你的自定义 Bean 有瑕疵。这时候再逐行检查返回类型到底是什么是否调用了afterPropertiesSet()或getObject()数据源是否注入正确GlobalConfig是否在构建 MyBatis-Plus 的MybatisSqlSessionFactoryBean时设置进去了还有一个容易踩的坑如果你覆盖了SqlSessionFactory但又没覆盖SqlSessionTemplate容器里可能存在一个来自你的 factory 一个来自自动配置的 template这种错位组合。MyBatis-Plus 自动配置的条件是没有 SqlSessionFactory 才创建但 SqlSessionTemplate 的自动装配条件可能基于另一个判断逻辑两者不同步就会导致 Mapper 拿到SqlSessionTemplate和SqlSessionFactory不是同一套报错会变得很诡异。所以手动接管时我总会成对定义 factory 和 template保持它们指向同一个实例。5. 常见变体与避坑速查5.1 版本冲突与兼容矩阵版本这个东西光背下来没用得知道去哪查。我把测试时常用的一组版本兼容表列出来方便你对照Spring Boot 版本MyBatis-Plus 版本备注2.3.x3.4.x兼容但注意 JDK82.5.x3.5.0 - 3.5.1需要一起升级 mybatis-spring2.6.x3.5.2注意 Spring Boot 2.6 对循环依赖默认禁止2.7.x3.5.2比较稳定3.0.x3.5.3.1需要 Spring Boot 3 / JDK17如果用到旧版 MP 会报兼容错Spring Boot 2.6 之后循环依赖被默认禁止如果 MyBatis-Plus 旧版本在装配时发生循环依赖会出现奇怪的启动失败。这种情况下不要盲目关掉循环依赖开关优先升级 MyBatis-Plus 版本。5.2 启动时 vs 运行时两种报错的实际差异同样是Property sqlSessionFactory or sqlSessionTemplate are required启动时报和运行时报排查方向差别很大。启动时报说明 Mapper 注册时容器里没有可用的SqlSessionFactory多半是自动配置被排除、Bean 定义被覆盖、数据源缺失。运行时才报说明 Mapper 对象已经创建成功但真正执行 SQL 时SqlSession 无法从某个地方获取这种情况大多指向动态数据源切换、多数据源路由、或者 MyBatis-Plus 拦截器链异常。两者不是一回事别混着排查。5.3 顺带踩过的坑数据源未初始化、拦截器失效再补充两个我经常见到的问题。第一个是数据源没初始化。如果你用的是自定义数据源配置比如写了一个DataSourceConfig类但ConfigurationProperties(prefix spring.datasource.druid)位置写错了数据源相关属性没有被加载DataSourceBean 创建时拿到空配置连接池启动失败。此时 MyBatis-Plus 自动配置判断它存在就不管了SqlSessionFactory 构建后因为底层的 DataSource 并没有真正连接等到查询时才爆出这个报错。排查特征就是上面提到过的自动配置报告里写did not find any beans。第二个是拦截器失效。MyBatis-Plus 的分页插件、乐观锁插件是通过 MybatisInterceptor 注入到 SqlSessionFactory 里的。如果你手动定义SqlSessionFactory时忘记添加这些拦截器SQL 执行时不仅分页失效某些场景下拦截器内部逻辑执行异常还会掩盖真正的错误。举个例子我在一个项目里手动接管过 SqlSessionFactory但漏配了分页插件结果 Limit 一直没生效前端表现是数据页数不对后端日志里却只出现了一个普通 SQL 执行错误。这类问题排查起来相当耗人所以建议手动接管时把下面这段加进去MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); factoryBean.setPlugins(interceptor);6. 一点实操体会周围同事经常让我帮看 MyBatis 相关的问题说实话这个报错虽然看起来简单但坑点真的很多。核心就一句话异常是在告诉你Spring 容器里拿不到 SqlSessionFactory而不是让你去 Mapper 上找毛病。排查时我的固定套路是先看依赖树再看启动类 exclude再看自动配置报告最后翻自定义配置类。按这个顺序大部分问题五分钟内能定位。手动接管 SqlSessionFactory 时我也习惯把 factory 和 template 成对配置并顺手把分页插件带上这样后续维护少了很多隐性故障。最后分享一个小技巧遇到这种容器对象缺失类报错不要只看异常的最后一行要往前翻Caused by部分最好把第一行到最后一行的 stack trace 整个复制下来检索。因为 spring 的异常链经常会嵌套两三层真正的根因往往藏在最底下那一行。项目有没有效、配置有没有被加载、数据源有没有起来都会在这一行上露出马脚。