✅ 一、MyBatis-Plus 异常类型总览
异常类型 |
核心含义 |
触发场景 |
MybatisPlusException |
通用运行时异常 |
配置错误、SQL错误、字段映射失败等 |
TooManyResultsException |
返回多条记录但只预期一条 |
使用 selectOne() 但返回多条 |
TableInfoException |
实体与表映射异常 |
实体缺少 @TableName 、字段不匹配 |
SqlParserException |
SQL解析失败 |
使用 QueryWrapper 或 LambdaWrapper 构造非法SQL |
SQLFeatureNotSupportedException |
JDBC不支持的操作 |
使用 LocalDateTime 但驱动版本过低 |
ClassNotFoundException |
类找不到 |
打包部署后 Lambda 表达式反序列化失败 |
MyBatisSystemException |
MyBatis 系统级异常 |
SQL语句或映射配置错误 |
✅ 二、操作步骤(排查 + 解决)
✅ 步骤1:快速定位异常类型
- 查看控制台异常名(如
MybatisPlusException: xxx
)
- 搜索异常全类名(如
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException
)
- 查看异常 message 定位字段、SQL 或配置项
✅ 步骤2:根据异常类型处理(典型场景)
📌 场景1:TooManyResultsException
User user = userMapper.selectOne(new QueryWrapper<User>().like("name", "张"));
- 原因:匹配到多条记录
- 解决:
- 使用
selectList()
替代
- 或加
.last("limit 1")
📌 场景2:TableInfoException: Cannot find table info cache
📌 场景3:SQLFeatureNotSupportedException: LocalDateTime
- 原因:MyBatis 3.5.1+ 不再处理
LocalDateTime
,JDBC 驱动不支持
- 解决:
- 升级
mysql-connector-java
至 8.0.20+
- 或使用
java.util.Date
替代
📌 场景4:ClassNotFoundException
(Lambda 查询打包后失败)
- 原因:MyBatis-Plus 3.3.2 以下版本在分离打包时无法反序列化 Lambda
- 解决:
- 升级 MyBatis-Plus 至 3.3.2+
- 或使用 XML 代替 Lambda 查询
✅ 三、常见错误清单(含解决方案)
错误信息 |
原因 |
快速解决方案 |
MybatisPlusException: property xxx cannot find column |
字段未映射 |
加 @TableField("real_col") |
Failed to bind properties under mybatis-plus.configuration... |
Spring Boot 2.2.0 构造器注入问题 |
升级 Spring Boot 至 2.2.2+ |
Conversion not supported for type java.time.LocalDateTime |
JDBC 驱动不支持 |
升级驱动或使用 Timestamp |
selectOne but found too many records |
查询条件不唯一 |
.last("limit 1") 或 selectList |
✅ 四、注意事项与使用技巧
类别 |
建议 |
参数校验 |
所有 selectOne() 前必须确保唯一性 |
字段映射 |
使用 @TableField 显式指定列名,避免自动映射失败 |
分页插件 |
必须在配置类中注册 MybatisPlusInterceptor 并添加 PaginationInnerInterceptor |
LambdaWrapper |
打包部署时避免使用 LambdaQueryWrapper ,推荐 QueryWrapper 或 XML |
全局异常处理 |
使用 @RestControllerAdvice 捕获 MybatisPlusException 并返回友好提示 |
✅ 五、最佳实践(异常预防 + 性能优化)
✅ 1. 统一异常处理(全局)
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MybatisPlusException.class)
public Result handleMP(MybatisPlusException e) {
return Result.fail("数据库操作异常:" + e.getMessage());
}
}
✅ 2. 分页查询防错
Page<User> page = new Page<>(1, 10);
IPage<User> result = userMapper.selectPage(page, new QueryWrapper<>());
✅ 3. 避免 N+1 查询
- 使用
JOIN
查询替代 @One(select = "...")
嵌套查询
- 或使用
fetchType = lazy
开启懒加载
✅ 4. 类型转换统一处理
- 自定义
TypeHandler
处理枚举、JSON 等复杂类型
- 使用
@TableField(typeHandler = XxxTypeHandler.class)
✅ 六、性能优化建议
维度 |
建议 |
批量操作 |
使用 ServiceImpl.saveBatch(list) 替代循环插入 |
缓存优化 |
使用 Redis 缓存分页结果,避免重复查询 |
日志控制 |
生产环境关闭 SQL 日志,开发环境开启 |
字段选择 |
避免 SELECT * ,使用 select("id", "name") 指定字段 |
✅ 七、总结:异常处理三步法
- 看异常名:识别是 MyBatis-Plus 还是 MyBatis 原生异常
- 读 message:字段名、SQL、配置项
- 查版本兼容性:MyBatis-Plus、Spring Boot、JDBC 驱动版本是否匹配