应统一捕获dataaccessexception处理sql超时与语法错误,返回脱敏提示;需配置mybatis、spring事务及hikaricp三层超时参数,并禁止前端暴露sql和堆栈信息。

Spring Boot 中对 MyBatis 执行 SQL 超时或语法错误做全局捕获,核心是两件事:一是统一拦截数据库异常防止敏感信息泄露,二是区分超时与语法错误类型做差异化响应。关键不在“捕获所有 Exception”,而在于精准识别 Spring 封装后的异常层级。
捕获 SQL 超时异常(如 Statement cancelled due to timeout)
SQL 超时由 JDBC 驱动抛出(如 MySQLTimeoutException),经 Spring 的 JdbcSQLExceptionTranslator 转为 org.springframework.dao.QueryTimeoutException,该异常继承自 DataAccessException。因此,推荐按父类统一捕获:
- 在全局异常处理器中添加
@ExceptionHandler(DataAccessException.class)方法 - 该方法可覆盖所有数据库操作异常,包括超时、连接中断、死锁等
- 返回统一提示如 “服务繁忙,请稍后重试”,不暴露 SQL 或堆栈细节
捕获 SQL 语法错误(如 BadSqlGrammarException)
语法错误通常源于拼写错误、表/字段名不存在、MyBatis 动态 SQL 渲染异常等,Spring 会将其转为 BadSqlGrammarException,它也属于 DataAccessException 子类。无需单独捕获该具体类型,复用上述 DataAccessException 处理器即可 —— 既简洁又全面。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
若需日志中快速区分语法类错误,可在 handler 内做类型判断:
-
if (e instanceof BadSqlGrammarException),记录更明确的 error 级别日志 - 仍返回相同前端提示,避免泄露数据库结构信息
确保 SQL 超时配置真正生效
仅捕获异常不够,必须让超时能真实触发。MyBatis 的超时控制分三层,需逐层确认:
-
MyBatis 层:通过
defaultStatementTimeout: 30(单位秒)设全局默认值,或在 XML 的<select timeout="60"></select>中设单条语句超时 -
Spring 事务层:若方法加了
@Transactional(timeout = 20),事务超时会优先于 SQL 超时生效,且抛出TransactionTimedOutException(不属于DataAccessException,需额外捕获) -
HikariCP 连接池层:
spring.datasource.hikari.connection-timeout控制获取连接的等待时间,与 SQL 执行超时无关,勿混淆
屏蔽原始 SQL 和堆栈,避免安全风险
默认异常响应可能包含完整 SQL(尤其开发环境开启 show-sql=true 时)或数据库错误详情(如 MySQL 的 You have an error in your SQL syntax)。务必做到:
- 全局异常处理器中,不调用
e.toString()或e.getMessage()直接返回前端 - 日志记录使用
log.error("DB error", e)完整输出堆栈,便于排查 - 前端响应体只含状态码、简明提示(如 “系统异常,请联系管理员”)、唯一 traceId(用于日志追踪)










