Java数据库异常处理核心是精准捕获SQLException:用try-with-resources自动关闭资源;按SQLState码分类处理(08xxx连接问题、23xxx约束冲突、42xxx语法错误);遍历异常链识别批量操作部分失败;对外脱敏返回通用错误码,对内完整日志留痕。

Java 中处理数据库操作异常,核心是围绕 SQLException 展开——它是 JDBC 操作失败时抛出的受检异常,必须显式捕获或声明。关键不在“能不能 catch”,而在于“怎么捕获得准、关得稳、判得清、回得妥”。
用 try-with-resources 自动关闭数据库资源
Connection、PreparedStatement、ResultSet 都实现了 AutoCloseable,手动在 finally 里 close 容易遗漏或嵌套冗长。直接用 try-with-resources 最安全:
- 资源声明写在 try() 小括号内,JVM 保证无论是否异常都会调用 close()
- 多个资源用分号隔开,关闭顺序与声明顺序相反(后声明的先关闭)
- 避免因未关闭导致连接池耗尽、句柄泄漏等生产事故
按 SQLState 分类处理错误类型
SQLException 的 getSQLState() 返回 5 位标准码,比 getMessage() 更稳定、比 getErrorCode() 更跨库。常见前缀含义:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 08xxx:连接类问题(如 08001 连接拒绝、08006 连接已关闭)→ 可重试或提示“服务暂时不可用”
- 23xxx:约束冲突(如 23505 唯一索引冲突、23503 外键违例)→ 转为用户友好提示,如“手机号已被注册”
- 42xxx:SQL 语法或对象不存在(如 42703 字段不存在、42P01 表不存在)→ 属于开发阶段问题,不应出现在生产环境
遍历异常链,不漏掉批量操作中的部分失败
执行 batch 操作或存储过程时,一个 SQLException 可能包裹多个子异常。只看主异常会丢失关键信息:
立即学习“Java免费学习笔记(深入)”;
- 用 for-each 遍历 e(SQLException 实现 Iterable<Throwable>)
- 对每个子异常检查 getSQLState() 和 getMessage(),分别记录或响应
- 尤其在 executeBatch() 后,需结合 getUpdateCounts() 判断哪些语句成功、哪些失败
对外脱敏,对内留痕
绝不能把原始 SQLException.getMessage() 直接返回给前端:
- 前端响应只返回通用业务码和模糊提示,如 “ERR_DATA_CONFLICT” + “数据已存在,请检查后重试”
- 完整异常堆栈、SQLState、errorCode、原始 SQL(若开启日志)必须记入服务端日志,供排查使用
- 敏感信息如表名、字段名、数据库版本、主机地址等,日志中应自动过滤或配置掩码

















