java中处理sqlexception的核心是精准分类、提取sqlstate与errorcode、遍历异常链、强制try-with-resources释放资源,并在dao层封装为自定义异常;不能仅依赖getmessage()或空catch,须记录sql语句、参数及诊断信息以支撑定位与响应。

Java 中处理 SQLException 的核心不是“抓到就完事”,而是分清错误性质、提取可靠信息、做精准响应。重点在于别只看 getMessage(),要善用 getSQLState() 和 getErrorCode(),同时不能忽略异常链。
用 try-with-resources 确保资源不泄漏
Connection、Statement、ResultSet 都实现了 AutoCloseable,必须用 try-with-resources 包裹,否则连接池耗尽、游标未释放等问题会很快暴露。
- 写法示例:直接在 try 后声明资源,JVM 自动调用 close(),哪怕发生 SQLException 也执行
- 避免手写 finally 块关资源——容易漏关、顺序错、二次异常掩盖主异常
- 不要复用同一个 PreparedStatement 执行不同 SQL,ResultSet 可能提前失效
优先用 getSQLState() 做跨库通用判断
SQLState 是 5 位字符串(如 "23505"),遵循 SQL 标准,MySQL 8.0+、PostgreSQL、Oracle、H2 全都支持。它比厂商码更稳定、可移植。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- "08S01" 表示连接中断,适合自动重试(配合退避策略)
- "23505" 表示唯一约束冲突,属于业务正常分支,应转为用户提示而非堆栈报警
- "40001" 是死锁,需回滚后重试,不延长事务时间
- 老版本 MySQL 驱动可能返回 "00000" 或 null,上线前务必实测验证
按场景选 getErrorCode():Oracle 业务异常最准,其他库慎用
getErrorCode() 返回整数,含义完全依赖数据库。Oracle 是特例:触发器中 RAISE_APPLICATION_ERROR(-20001, ...) → Java 中 ex.getErrorCode() 直接返回 20001,可直接用于 switch 或 if 判断。
- MySQL:1062 = 重复键,但驱动版本不同可能行为不一,建议仅作辅助定位
- PostgreSQL:常返回 0 或负数(如 -1),实际应以 SQLState 为准
- Oracle:getErrorCode() == 20001 就代表你定义的“余额不足”,无需解析消息字符串
- 返回 0 或负数时,说明不是业务主动抛出的错误,可能是网络或驱动层问题
遍历异常链,不漏掉真实根因
批量操作、存储过程、连接池回收异常等场景下,SQLException 往往带 getNextException() 链。只处理第一个,可能错过真正失败的原因。
- 用 for-each 遍历异常链:for (Throwable t : e) { ... }
- 每个节点都可调用 getSQLState() 和 getErrorCode(),取首个非空/非零值更可靠
- 日志中记录完整链,方便排查“为什么 insert 成功了却报错”这类隐蔽问题
- Spring JdbcTemplate 等框架会把 SQLException 包装成 unchecked 异常,需用 getCause() 向下挖到底层 SQLException
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










