✅ 一、MyBatis-Plus 异常类型总览

异常类型 核心含义 触发场景
MybatisPlusException 通用运行时异常 配置错误、SQL错误、字段映射失败等
TooManyResultsException 返回多条记录但只预期一条 使用 selectOne() 但返回多条
TableInfoException 实体与表映射异常 实体缺少 @TableName、字段不匹配
SqlParserException SQL解析失败 使用 QueryWrapperLambdaWrapper 构造非法SQL
SQLFeatureNotSupportedException JDBC不支持的操作 使用 LocalDateTime 但驱动版本过低
ClassNotFoundException 类找不到 打包部署后 Lambda 表达式反序列化失败
MyBatisSystemException MyBatis 系统级异常 SQL语句或映射配置错误

✅ 二、操作步骤(排查 + 解决)

✅ 步骤1:快速定位异常类型

  1. 查看控制台异常名(如 MybatisPlusException: xxx
  2. 搜索异常全类名(如 com.baomidou.mybatisplus.core.exceptions.MybatisPlusException
  3. 查看异常 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

  • 原因:实体类未加 @TableName 或表名拼写错误
  • 解决
    @TableName("sys_user")
    public class User {}
    

📌 场景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") 指定字段

✅ 七、总结:异常处理三步法

  1. 看异常名:识别是 MyBatis-Plus 还是 MyBatis 原生异常
  2. 读 message:字段名、SQL、配置项
  3. 查版本兼容性:MyBatis-Plus、Spring Boot、JDBC 驱动版本是否匹配