ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、视频、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# MyBatis 常用异常类总结表 | 类别 | 类名 | 包名 | 是否受检 | 主要用途/场景 | 继承关系 | 触发时机 | |------|------|------|----------|---------------|----------|----------| | **核心异常** | `PersistenceException` | org.apache.ibatis.exceptions | 否 | MyBatis所有异常的基类 | `RuntimeException` | MyBatis框架通用异常基类 | | | `IbatisException` | org.apache.ibatis.exceptions | 否 | 旧版本异常基类(已弃用) | `RuntimeException` | 旧版本MyBatis异常 | | **配置异常** | `BuilderException` | org.apache.ibatis.builder | 否 | 构建器异常 | `PersistenceException` | SQL映射构建、配置解析错误 | | | `ParsingException` | org.apache.ibatis.parsing | 否 | 解析异常 | `PersistenceException` | XML/注解配置解析失败 | | | `TypeException` | org.apache.ibatis.type | 否 | 类型处理异常 | `PersistenceException` | 类型处理器注册、转换失败 | | | `BindingException` | org.apache.ibatis.binding | 否 | 绑定异常 | `PersistenceException` | Mapper接口与XML绑定失败 | | | `ReflectionException` | org.apache.ibatis.reflection | 否 | 反射异常 | `PersistenceException` | 反射操作失败、属性访问异常 | | | `TooManyResultsException` | org.apache.ibatis.exceptions | 否 | 查询结果过多异常 | `PersistenceException` | 查询返回多个结果但期望单个 | | **SQL执行异常** | `SqlSessionException` | org.apache.ibatis.exceptions | 否 | SQL会话异常 | `PersistenceException` | SqlSession操作失败、事务异常 | | | `ExecutorException` | org.apache.ibatis.executor | 否 | 执行器异常 | `PersistenceException` | SQL执行器错误、批处理失败 | | | `BatchExecutorException` | org.apache.ibatis.executor | 否 | 批处理异常 | `ExecutorException` | 批处理操作失败 | | | `StatementHandlerException` | org.apache.ibatis.executor.statement | 否 | 语句处理器异常 | `PersistenceException` | Statement/PreparedStatement处理错误 | | | `ResultSetHandlerException` | org.apache.ibatis.executor.resultset | 否 | 结果集处理器异常 | `PersistenceException` | 结果集映射、处理错误 | | | `ParameterHandlerException` | org.apache.ibatis.executor.parameter | 否 | 参数处理器异常 | `PersistenceException` | SQL参数处理、绑定失败 | | **事务异常** | `TransactionException` | org.apache.ibatis.transaction | 否 | 事务异常 | `PersistenceException` | 事务管理、提交/回滚失败 | | | `NestedTransactionException` | org.apache.ibatis.transaction | 否 | 嵌套事务异常 | `TransactionException` | 嵌套事务不支持或错误 | | **缓存异常** | `CacheException` | org.apache.ibatis.cache | 否 | 缓存异常 | `PersistenceException` | 缓存操作失败、序列化错误 | | | `SerializationException` | org.apache.ibatis.cache | 否 | 序列化异常 | `CacheException` | 缓存对象序列化/反序列化失败 | | **插件异常** | `PluginException` | org.apache.ibatis.plugin | 否 | 插件异常 | `PersistenceException` | 拦截器插件执行失败 | | | `InterceptorException` | org.apache.ibatis.plugin | 否 | 拦截器异常 | `PluginException` | 拦截器配置或执行错误 | | **脚本异常** | `ScriptingException` | org.apache.ibatis.scripting | 否 | 脚本异常 | `PersistenceException` | 动态SQL脚本解析失败 | | | `ExpressionEvaluatorException` | org.apache.ibatis.scripting | 否 | 表达式求值异常 | `ScriptingException` | OGNL/MVEL表达式求值错误 | | **数据源异常** | `DataSourceException` | org.apache.ibatis.datasource | 否 | 数据源异常 | `PersistenceException` | 数据源获取连接失败 | | **日志异常** | `LogException` | org.apache.ibatis.logging | 否 | 日志异常 | `PersistenceException` | 日志框架初始化失败 | | **IO异常** | `IOException` | java.io | 是 | IO异常(MyBatis包装) | `Exception` | 配置文件读取、资源加载失败 | | **资源异常** | `ResourceLoadException` | org.apache.ibatis.io | 否 | 资源加载异常 | `PersistenceException` | 类路径资源加载失败 | | **XML解析异常** | `XMLParseException` | org.apache.ibatis.parsing | 否 | XML解析异常 | `ParsingException` | XML配置文件解析错误 | | **映射异常** | `ResultMapException` | org.apache.ibatis.mapping | 否 | 结果映射异常 | `PersistenceException` | 结果集到对象映射失败 | | | `InvalidResultMapException` | org.apache.ibatis.mapping | 否 | 无效结果映射异常 | `ResultMapException` | 结果映射配置错误 | | **注解异常** | `AnnotationException` | org.apache.ibatis.annotations | 否 | 注解异常 | `PersistenceException` | 注解配置错误、重复注解 | | **会话异常** | `SessionException` | org.apache.ibatis.session | 否 | 会话异常 | `PersistenceException` | SqlSession状态异常 | | | `SqlSessionClosedException` | org.apache.ibatis.session | 否 | 会话关闭异常 | `SessionException` | 使用已关闭的SqlSession | | **工具类** | `ExceptionFactory` | org.apache.ibatis.exceptions | - | 异常工厂类 | - | 异常包装和创建工具 | ## MyBatis 异常分类说明 ### 1. **核心异常类** - **`PersistenceException`**: MyBatis所有异常的基类,所有自定义异常都应继承此类 - **`IbatisException`**: 旧版本异常基类,新版本已弃用,建议使用`PersistenceException` ### 2. **配置异常** - **`BuilderException`**: 配置构建时异常,如XML配置错误、映射文件格式问题 - **`TypeException`**: 类型处理器注册失败、Java类型与JDBC类型不匹配 - **`BindingException`**: Mapper接口与XML映射文件绑定失败,方法找不到对应的SQL语句 ### 3. **SQL执行异常** - **`TooManyResultsException`**: 查询返回多个结果但期望单个结果时抛出 - **`ExecutorException`**: SQL执行器异常,包括简单执行器、重用执行器、批处理执行器 - **`BatchExecutorException`**: 批处理操作失败时抛出 ### 4. **事务异常** - **`TransactionException`**: 事务管理异常,包括JDBC事务、Managed事务等 - **`NestedTransactionException`**: 嵌套事务相关异常 ### 5. **常用异常处理示例** ```java // 1. 查询单个结果但返回多个的处理 try { User user = sqlSession.selectOne("com.example.mapper.UserMapper.selectById", 1); } catch (TooManyResultsException e) { log.error("查询到多个结果但期望单个: {}", e.getMessage()); // 改用查询列表 List<User> users = sqlSession.selectList("com.example.mapper.UserMapper.selectById", 1); return users.isEmpty() ? null : users.get(0); } // 2. 处理Mapper绑定异常 try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.selectById(1); } catch (BindingException e) { log.error("Mapper绑定失败: {}", e.getMessage()); // 检查XML映射文件是否存在或SQL语句是否正确 if (e.getMessage().contains("does not contain value")) { log.error("请检查XML文件中SQL语句的id是否正确"); } } // 3. 处理类型转换异常 try { // 执行查询 sqlSession.selectList("com.example.mapper.UserMapper.selectAll"); } catch (TypeException e) { log.error("类型处理失败: {}", e.getMessage()); // 检查实体类字段类型与数据库字段类型是否匹配 // 或注册自定义类型处理器 } // 4. 处理SQL执行异常 try { sqlSession.insert("com.example.mapper.UserMapper.insert", user); sqlSession.commit(); } catch (ExecutorException e) { log.error("SQL执行失败: {}", e.getMessage()); sqlSession.rollback(); // 根据具体错误类型处理 if (e.getCause() instanceof SQLIntegrityConstraintViolationException) { throw new BusinessException("数据完整性约束错误"); } } ``` ### 6. **MyBatis全局异常处理** ```java @RestControllerAdvice public class MyBatisExceptionHandler { @ExceptionHandler(TooManyResultsException.class) public Result<Void> handleTooManyResultsException(TooManyResultsException e) { log.warn("查询结果过多: {}", e.getMessage()); return Result.fail("查询到多个结果,请优化查询条件"); } @ExceptionHandler(BindingException.class) public Result<Void> handleBindingException(BindingException e) { log.error("Mapper绑定异常: {}", e.getMessage()); return Result.fail("数据映射配置错误,请联系管理员"); } @ExceptionHandler(PersistenceException.class) public Result<Void> handlePersistenceException(PersistenceException e) { log.error("MyBatis持久化异常: {}", e.getMessage(), e); // 根据不同子类异常处理 if (e instanceof ExecutorException) { return Result.fail("数据库操作失败,请稍后重试"); } else if (e instanceof TransactionException) { return Result.fail("事务处理异常,请检查数据一致性"); } return Result.fail("系统数据处理异常"); } @ExceptionHandler(SQLException.class) public Result<Void> handleSQLException(SQLException e) { log.error("数据库SQL异常: {}", e.getMessage(), e); // 处理常见的SQL状态码 int errorCode = e.getErrorCode(); String sqlState = e.getSQLState(); if ("23000".equals(sqlState) || errorCode == 1062) { return Result.fail("数据已存在,请勿重复添加"); } else if ("22001".equals(sqlState)) { return Result.fail("数据长度超出限制"); } else if ("28000".equals(sqlState)) { return Result.fail("数据库连接权限不足"); } return Result.fail("数据库操作失败"); } } ``` ### 7. **MyBatis异常处理最佳实践** ```java public class UserService { @Autowired private SqlSessionFactory sqlSessionFactory; public User getUserById(Long id) { try (SqlSession sqlSession = sqlSessionFactory.openSession()) { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.selectById(id); } catch (TooManyResultsException e) { // 记录日志并返回null或抛出业务异常 log.warn("用户ID:{} 查询到多个结果", id); throw new BusinessException("用户数据异常"); } catch (BindingException e) { // 检查Mapper配置 log.error("UserMapper配置错误", e); throw new SystemException("系统配置错误"); } catch (PersistenceException e) { // 其他MyBatis异常 log.error("查询用户失败", e); throw new SystemException("数据库操作失败"); } } public void batchInsertUsers(List<User> users) { try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper mapper = sqlSession.getMapper(UserMapper.class); for (User user : users) { mapper.insert(user); } sqlSession.commit(); } catch (BatchExecutorException e) { log.error("批处理插入失败", e); throw new BusinessException("批量操作失败"); } catch (TransactionException e) { log.error("事务提交失败", e); throw new SystemException("事务处理异常"); } } } ``` ### 8. **MyBatis与Spring整合的异常处理** ```java @Repository public class UserDaoImpl implements UserDao { @Autowired private SqlSessionTemplate sqlSessionTemplate; @Override @Transactional(rollbackFor = Exception.class) public int insertUser(User user) { try { UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class); return mapper.insert(user); } catch (DataAccessException e) { // Spring会将MyBatis异常包装为DataAccessException log.error("插入用户失败", e); // 获取根本原因 Throwable cause = e.getCause(); if (cause instanceof PersistenceException) { // 处理MyBatis原生异常 handleMyBatisException((PersistenceException) cause); } throw new BusinessException("保存用户失败"); } } private void handleMyBatisException(PersistenceException e) { if (e instanceof TooManyResultsException) { // 处理查询结果过多 } else if (e instanceof ExecutorException) { // 处理执行器异常 } } } ``` ## MyBatis异常处理总结 1. **异常继承体系**:所有MyBatis异常都继承自`PersistenceException`,属于运行时异常 2. **异常分类清晰**:按功能模块分类,便于定位问题 3. **与Spring整合**:Spring会将MyBatis异常包装为`DataAccessException` 4. **实际开发建议**: - 对`TooManyResultsException`、`BindingException`等常见异常进行专门处理 - 使用try-with-resources确保SqlSession正确关闭 - 在事务操作中注意异常回滚 - 结合具体业务场景定义业务异常 通过合理处理MyBatis异常,可以提高系统的健壮性和可维护性。