JDBC异常SQLException的捕获与处理 您所在的位置:网站首页 行程码查询数据异常是什么原因 JDBC异常SQLException的捕获与处理

JDBC异常SQLException的捕获与处理

2024-07-13 03:23| 来源: 网络整理| 查看: 265

最近自己在实现一个通用的ID生成器,写了个内存版,后面实现mysql的持久化器时,考虑到低侵入性,使用原生JDBC来进行编程。 有一个地方实现,想通过直接insert来插入一条数据,但如果唯一字段冲突,即表明当前数据已存在,需要提示出来,让程序能正常响应。

Connection connection = dataSource.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("insert into walnut.app_info (app_id, app_name)values(?,?);")

如上面的sql,app_id是唯一索引,那么需要捕获主键冲突异常,然后做处理。 怎么做?

SQLException是一个提供了数据库访问错误或其他错误信息的异常,我们可以通过捕获来获取异常信息。 SQLException有两个用来获取判断具体错误信息的函数:

getSQLState() :返回一个代码,有五位的字母和数字组成 。多数的代码由 ISO/ANSI 和 Open Group(X/Open) 标准化,但是仍然存在部分的代码由数据库提供商自行实现。getErrorCode():与 SQLState 不同,错误代码是由数据库提供商自行定义的整数值。通常是底层数据库返回的实际错误码。

如果我们要捕获特定的异常来做特殊处理,则可以通过上面的两个函数来处理。但考虑到getErrorCode()更加的接近实际错误,所以我们可以通过getErrorCodel()来判断。

想起来,我们在用Spring的时候,如果要捕获主键冲突,用的是DuplicateKeyException这个异常类,该类由Spring框架内定义的。本质上底层还是用的JDBC,那么它是怎么知道什么错误码转换的DuplicateKeyException? 带着这个疑问,瞄了眼它内部:通过org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator#doTranslate来将SQLException转换成它自身定义的特定异常,方便外部捕获使用。 该方法中,可看到如下代码:

//this.sqlErrorCodes 即 org.springframework.jdbc.support.SQLErrorCodes if (Arrays.binarySearch(this.sqlErrorCodes.getDuplicateKeyCodes(), errorCode) >= 0) { this.logTranslation(task, sql, sqlEx, false); return new DuplicateKeyException(this.buildMessage(task, sql, sqlEx), sqlEx); }

其中org.springframework.jdbc.support.SQLErrorCodes中定义了一系列的特定异常错误码。

private String[] badSqlGrammarCodes = new String[0]; private String[] invalidResultSetAccessCodes = new String[0]; private String[] duplicateKeyCodes = new String[0]; private String[] dataIntegrityViolationCodes = new String[0]; private String[] permissionDeniedCodes = new String[0]; private String[] dataAccessResourceFailureCodes = new String[0]; private String[] transientDataAccessResourceCodes = new String[0]; private String[] cannotAcquireLockCodes = new String[0]; private String[] deadlockLoserCodes = new String[0]; private String[] cannotSerializeTransactionCodes = new String[0];

那么我们怎么知道数组里面是啥?Spring定义在了哪里?全局搜一下吧,果不其然,我们通过IDEA全局搜:duplicateKeyCodes 在这里插入图片描述 sql-error-codes.xml这个文件就是Spring配置的JDBC的异常码,里面涵盖了好几种DB,我们用的mysql,就看mysql的定义。通过Spring的这个文件,我们也知道了mysql的主键冲突,返回的就是1062的错误码。

接下来就是应用到我们代码中了,参考Spring的转换实现。

public class MySqlJDBCErrorCodes { public static final String[] badSqlGrammarCodes = {"1054", "1064", "1146"}; public static final String[] duplicateKeyCodes = {"1062"}; public static final String[] dataIntegrityViolationCodes = {"630", "839", "840", "893", "1169", "1215", "1216", "1217", "1364", "1451", "1452", "1557"}; public static final String[] dataAccessResourceFailureCodes = {"1"}; public static final String[] cannotAcquireLockCodes = {"1205"}; public static final String[] deadlockLoserCodes = {"1213"}; static { Arrays.sort(badSqlGrammarCodes); Arrays.sort(duplicateKeyCodes); Arrays.sort(dataIntegrityViolationCodes); Arrays.sort(dataAccessResourceFailureCodes); Arrays.sort(cannotAcquireLockCodes); Arrays.sort(deadlockLoserCodes); } } ---- //示例 try { preparedStatement.executeUpdate(); } catch (SQLException sqlException) { String errorCode = Integer.toString(sqlException.getErrorCode()); if (Arrays.binarySearch(MySqlJDBCErrorCodes.duplicateKeyCodes, errorCode) >= 0) { throw new DuplicateKeyException(String.format("[appid=%s] is exist!", input.getAppId())); } throw sqlException; }

以上,就是我用JDBC编程的一段小经历,通过借鉴Spring是怎么做的异常转换,来取得自己需要的实现,做个记录望能起到帮助。

来个传送门:SQLSTATE各种状态码



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有