在 Spring Boot 项目中接入MyBatis-Plus时,很多人都会遇到下面这个异常:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): cn.xxx.xxxmapper.HaMapper.insert表面看起来像是Mapper 或 XML 没配置好,但如果你已经:
Mapper 能正常注入
XML 的
select能用唯独
BaseMapper.insert()报错
👉 那99% 是 SqlSessionFactoryBean 配置导致的。
本文通过一次真实踩坑经历,系统讲清楚:
问题产生的根因
为什么 MyBatis-Plus 特别容易中招
正确 & 官方推荐的解决方案
一、问题现象
异常信息如下:
Invalid bound statement (not found): cn.ha.xx.xxmapper.HaMapper.insert对应代码:
haMapper.insert(entity);而HaMapper定义如下:
public interface HaMapper extends BaseMapper<HaEntity> { }看起来完全没问题,但一运行就报错。
二、为什么 MyBatis-Plus 会在 insert 上报错?
1️⃣ BaseMapper 的 SQL 是「自动注入」的
这是关键背景。
insert / deleteById / updateById并不在 XML 中
而是在SqlSessionFactory 初始化时
由 MyBatis-Plus 动态注册
这个注册过程只会发生在:MybatisSqlSessionFactoryBean中。
2️⃣ 手动配置 SqlSessionFactoryBean 会发生什么?
很多项目(尤其是老项目 / 多数据源)都会写类似配置:
@Bean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); return factoryBean.getObject(); }⚠️问题就在这里。
你虽然成功创建了 SqlSessionFactory,但:
❌ 绕开了 MyBatis-Plus 的自动配置
❌ BaseMapper 的 CRUD SQL 根本没有被注入
结果就是:
XML 里的 SQL 能用 BaseMapper.insert → Invalid bound statement
三、如何快速判断是不是这个坑?
你可以对照下面这个表:
| 现象 | 是否命中该问题 |
|---|---|
| Mapper 能注入 | ✅ |
| XML select 正常 | ✅ |
| BaseMapper.insert 报错 | ✅ |
| 项目中存在 SqlSessionFactoryBean | 100% 命中 |
如果你手动 new 了 SqlSessionFactoryBean,几乎可以直接确认原因。
四、正确的解决方案(官方推荐)
✅ 方案一:删除自定义 SqlSessionFactory(最推荐)
如果你不是多数据源、也没有特别定制需求:
@Configuration @MapperScan("cn.ha.xx.xxmapper") public class MybatisPlusConfig { }只保留依赖:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency>👉 MyBatis-Plus 会自动:
使用
MybatisSqlSessionFactoryBean注入 BaseMapper CRUD
扫描 Mapper
这是最稳妥、最不容易出问题的方式。
✅ 方案二:必须自定义时,用 MybatisSqlSessionFactoryBean
如果你确实需要手动配置(如插件、多数据源):
@Bean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources("classpath:/mapper/**/*.xml") ); return factory.getObject(); }❗重点只有一句:
不要再使用
SqlSessionFactoryBean
✅ 方案三:多数据源场景(高频踩坑)
@Bean @Primary public SqlSessionFactory primarySqlSessionFactory(DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(dataSource); return factory.getObject(); }配合:
@MapperScan( basePackages = "cn.ha.xx.xxmapper", sqlSessionFactoryRef = "primarySqlSessionFactory" )五、为什么这个坑特别隐蔽?
原因只有一个:
它不是配置错误,而是“配置覆盖成功了,但逻辑被绕开了”
不报 Bean 冲突
不报启动异常
直到你调用
BaseMapper.insert才炸
非常具有迷惑性。
六、总结
如果你在 MyBatis-Plus 中遇到:
Invalid bound statement (not found): xxxMapper.insert
请第一时间检查:
❗ 是否手动配置了 SqlSessionFactoryBean
记住一句话就够了:
👉 用 MyBatis-Plus,就要让它掌控 SqlSessionFactory