必须用 sqlexception.geterrorcode() 提取数字码,如 ora-00001 返回 1,ora-00060 返回 60,该值跨驱动稳定且不受国际化或日志截断影响;需通过 getcause() 逐层提取根 sqlexception,并结合元数据查询约束名对应业务字段。
必须用 sqlexception.geterrorcode() 提取数字码,别解析 getmessage() 字符串——这是唯一跨驱动、跨框架、不被国际化或日志截断破坏的稳定方式。
怎么从 SQLException 里准确拿到 ORA-00001 这类错误码
Oracle JDBC 驱动把真实错误码直接塞进 getErrorCode() 返回值里:ORA-00001 → 返回 1,ORA-00060 → 返回 60,ORA-20001(触发器抛出)→ 返回 20001。这个值不受 Spring/Hibernate 包装影响,也不随语言环境变化。
- ✅ 正确写法:
if (ex.getErrorCode() == 1)或if (ex.getErrorCode() == 60) - ❌ 错误写法:
ex.getMessage().contains("ORA-00001")—— 日志可能被截断、转大写、加前缀,甚至被中间件过滤掉 "ORA-" 字样 - ⚠️ 注意:
getSQLState()返回的是 SQL 标准码(如"23000"),它不区分ORA-00001和ORA-02291,不能用于精准判断
Spring + MyBatis/Hibernate 场景下,异常早被包装了好几层怎么办
MyBatis 把原始 SQLException 包进 PersistenceException 或 DataIntegrityViolationException;Hibernate 更常套成 ConstraintViolationException。但根因仍是 Oracle 报的 SQLException,得一层层 getCause() 挖到底。
- 推荐写个工具方法:
extractRootSQLException(Throwable t),循环调用t.getCause()直到找到instanceof SQLException - 不要只 catch
SQLIntegrityConstraintViolationException—— WebLogic 或某些连接池会把它再包进BatchUpdateException - 在统一异常处理器里拦截
Exception.class,而不是按具体子类分散 catch,避免漏判
拿到 ORA-00001 后,怎么知道是哪个字段重复了
Oracle 错误消息里带的约束名(如 SYS_C0012321)是系统生成的,没法直接告诉用户“手机号已存在”。必须反查元数据,把约束名映射回业务字段。
- 执行这条 SQL 查字段:
SELECT cols.column_name, cons.table_name FROM user_constraints cons JOIN user_cons_columns cols ON cons.constraint_name = cols.constraint_name WHERE cons.constraint_name = 'SYS_C0012321' - 用
user_constraints而不是all_constraints,速度快、权限要求低,开发/测试环境够用 - 查出来是
mobile字段,就返回 “手机号已被注册”,而不是笼统说 “唯一约束冲突”
为什么不能只靠 try-catch 包住整个 service 方法来处理 ORA 异常
ORA 异常发生在具体 SQL 执行点,不是事务提交时才抛。如果 DML 操作和 catch 块隔得太远,或者被 AOP 代理拆开,异常根本捕不到,或者捕到时事务状态已不可用。
- 错误模式:先
mapper.insert(...),再transaction.commit(),只在 commit 外 try-catch ——insert失败时异常早就抛出了,根本进不了 commit - 正确姿势:DML 和 catch 紧挨着,比如
stmt.executeUpdate(...)后立刻catch (SQLException ex) - Spring 环境下,
@Transactional方法里直接@Retryable无效,因为死锁异常实际发生在afterCompletion阶段,方法早已返回
最易被忽略的一点:getErrorCode() 返回 0 或负数(比如 -1)时,大概率不是 Oracle 业务错误,而是连接中断、超时、驱动加载失败这类底层问题,得走另一套恢复逻辑,别跟 ORA-00001 一起处理。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











