捕获 sqlexception 需分层识别错误类型、精准响应、安全释放资源并隔离敏感信息;应使用 try-with-resources 确保资源自动关闭,按 sqlstate 或 errorcode 分类处理,遍历异常链提取根因,事务中异常须显式回滚,避免解析 getmessage() 字符串。

捕获 SQLException 不只是简单地 try-catch,关键在于分层识别错误类型、精准响应、安全释放资源,并隔离敏感信息。直接打印 e.printStackTrace() 或只用 getMessage() 返回前端,既不安全也不实用。
用 try-with-resources 确保资源零泄漏
Connection、PreparedStatement、ResultSet 都实现了 AutoCloseable,必须放在 try() 括号内,由 JVM 自动关闭。手动 close 容易遗漏或在异常路径下跳过,导致连接池耗尽。
- 写法示例:
try (Connection conn = dataSource.getConnection();<br> PreparedStatement ps = conn.prepareStatement("INSERT INTO users(name) VALUES (?)")) {<br> ps.setString(1, "Alice");<br> ps.executeUpdate();<br>} catch (SQLException e) {<br> // 异常处理逻辑<br>} - 即使 executeUpdate() 抛出异常,ps 和 conn 仍会自动关闭,无需 finally 块
- 避免嵌套 try(如 ResultSet 再套一层 try-with-resources),保持扁平结构更清晰
按 SQLState 或 errorCode 分类判断错误语义
SQLState 是标准五位码(如 "23000" 表示完整性约束违规),errorCode 是数据库厂商码(如 Oracle 的 1 对应 ORA-00001)。二者结合才能准确定位问题。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- "08xxx" 开头(如 "08001"):连接类异常 → 可重试或降级
- "23xxx" 开头(如 "23000"):数据约束冲突 → 映射到业务提示,如“手机号已注册”
- errorCode == 1(Oracle)或 1062(MySQL):唯一键冲突 → 不报错,返回用户友好提示
- errorCode == 1205(SQL Server)或 60(Oracle):死锁 → 记录日志并自动重试一次
- 别解析 getMessage() 字符串匹配 "ORA-" 或 "Duplicate entry" —— 日志截断、国际化、中间件包装都会让它不可靠
遍历异常链,不漏掉批量操作中的多个失败
执行 batch 操作时,一个 SQLException 可能包含多个子异常,仅看首层会丢失关键错误点。
- 用增强 for 遍历异常链:
for (Throwable t : e) {<br> if (t instanceof SQLException se) {<br> System.err.println("SQLState: " + se.getSQLState());<br> System.err.println("Code: " + se.getErrorCode());<br> }<br>} - MyBatis/Hibernate 包装后,原始 SQLException 往往藏在 getCause() 多层之下,建议封装工具方法 extractRootSQLException(Throwable)
- 对批量插入场景,可结合 getUpdateCounts() 判断哪些批次成功、哪些失败,再针对性补偿
事务中发生异常必须显式回滚
开启事务后(setAutoCommit(false)),一旦捕获 SQLException,必须立即 rollback,否则连接可能带着未提交的脏状态归还连接池。
- 回滚前先检查 connection 是否有效(isClosed()),避免对已关闭连接调用 rollback 报新异常
- rollback 后不要继续使用该 connection 执行其他语句
- Spring 环境下优先用 @Transactional + rollbackFor=SQLException.class,由框架统一管理;纯 JDBC 场景则需手写 rollback 逻辑
- 注意:rollback 不会自动恢复 auto-commit 状态,若需复用连接,应显式 setAutoCommit(true)
精细化处理的核心是把技术异常翻译成业务动作:该重试的重试,该提示用户的提示,该记录日志的脱敏记录,该释放的资源绝不拖延。不是所有 SQLException 都要告警,也不是所有都要抛给上层。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










