当前位置:网站首页>JDBC异常SQLException的捕获与处理
JDBC异常SQLException的捕获与处理
2022-07-22 10:31:00 【lucky_白杨】
最近自己在实现一个通用的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各种状态码
边栏推荐
- Usage and precautions of accumulator used in spark
- Typora download and simple use tutorial
- Introduction to machine learning: support vector machine-6
- CentOS安装mysql数据库
- 网站别黑了怎么解决?如何处理网站被黑问题详解
- Elastic Search 学习入门之插件安装(五)
- DNS劫持如何预防、DNS是什么?DNS劫持详解
- Leetcode 209. subarray with the smallest length
- 数据库使用QueryRunner模拟封装
- Generate an external inspection script to delete all tables in the database
猜你喜欢
Don't hack the website. How to solve it? How to deal with the problem of website being hacked
[reading notes] MySQL architecture and storage engine
What are the definitions and principles of domain name hijacking and the solutions to domain name hijacking
百度首页被tn劫持的办法有那些、两种解决百度劫持的方法
What is the meaning of DNS hijacking, the principle of DNS hijacking and several solutions
进程的互斥、同步
dns被劫持了怎么处理 5种方法教你处理
What is network hijacking? How to repair web pages that have been tampered with and hijacked (final scheme) how to repair web page hijacking?
Typora download and simple use tutorial
SSM框架整合
随机推荐
LeetCode21——Merge two sorted lists——Iteration or recursion
网络劫持是什么?网页被篡改劫持怎么修复(终级方案)网页劫持如何修复?
《预训练周刊》第38期: Transformer、BERT结构优化
YOLO v1、v2、v3
机器学习入门:支持向量机-6
Websites jump inexplicably. What is website hijacking from Baidu? How to solve Baidu snapshot hijacking
LeetCode206——反转链表
DNS劫持如何预防、DNS是什么?DNS劫持详解
NC4 judge whether there is a ring in the linked list
Elastic Search 学习入门之核心概念(四)
json按格式逐行输出到文件
How to deal with DNS hijacked? Five ways to deal with it
Flask cross domain
The well-known software adsafe conceals malicious code to hijack traffic from many websites
机器学习入门:线性回归-1
LeetCode0003——longest substring without repeating characters——Sliding Window
离线日志采集统计分析
Elastic Search 学习入门之restful的高级查询操作(九)
Dense Passage Retrieval for Open-Domain Question Answering笔记
What should I do after the domain name of website security is hijacked and the domain name is hijacked!!!