写作时间:2019-08-18
Spring Boot: 2.1 ,JDK: 1.8, IDE: IntelliJ IDEA
一致异常层级结构(Consistent Exception Hierarchy):
Spring提供了以DataAccessException为异常基类。所有的数据库操作异常信息都会包括在异常基类中,不用担心异常信息的丢失.
通过SQLErrorCodeSQLExceptionTranslator解析错误码
ErrorCode 定义
SQLErrorCodes 源码位置
org.springframework.jdbc.support.SQLErrorCodes
public class SQLErrorCodes {
@Nullable
private String[] databaseProductNames;
private boolean useSqlStateForTranslation = false;
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];
@Nullable
private CustomSQLErrorCodesTranslation[] customTranslations;
@Nullable
private SQLExceptionTranslator customSqlExceptionTranslator;
...
}
注释:
错误码配置信息
org.springframework.jdbc.support.sql-error-codes.xml
<bean id="H2" class="org.springframework.jdbc.support.SQLErrorCodes">
<property name="badSqlGrammarCodes">
<value>42000,42001,42101,42102,42111,42112,42121,42122,42132value>
property>
<property name="duplicateKeyCodes">
<value>23001,23505value>
property>
<property name="dataIntegrityViolationCodes">
<value>22001,22003,22012,22018,22025,23000,23002,23003,23502,23503,23506,23507,23513value>
property>
<property name="dataAccessResourceFailureCodes">
<value>90046,90100,90117,90121,90126value>
property>
<property name="cannotAcquireLockCodes">
<value>50200value>
property>
bean>
注释:上面展示了H2的配置信息
参照教程【SpringBoot 2.1 | 第一篇:构建第一个SpringBoot工程】新建一个Spring Boot项目,名字叫demodberrorcode, 在目录src/main/java/resources
下找到配置文件application.properties
,重命名为application.yml
。
在Dependency中选择
Developer Tools > Lombok
Web > Spring Web Starter
SQL > H2 DataBase / JDBC API
Ops > Spring Boot Actuator。
ANSI - American National Standards Institute
Support classes to provide ANSI color output.
src > main > resources > application.yml
spring:
output:
ansi:
enabled: always
路径 src > main > resources > schema.sql
CREATE TABLE FOO (ID INT IDENTITY, BAR VARCHAR(64));
com.zgpeace.demodberrorcode.CustomDuplicatedKeyException
package com.zgpeace.demodberrorcode;
import org.springframework.dao.DuplicateKeyException;
public class CustomDuplicatedKeyException extends DuplicateKeyException {
public CustomDuplicatedKeyException(String msg) {
super(msg);
}
public CustomDuplicatedKeyException(String msg, Throwable cause) {
super(msg, cause);
}
}
路径 src > main > resources > sql-error-codes.xml
<beans>
<bean id="H2" class="org.springframework.jdbc.support.SQLErrorCodes">
<property name="badSqlGrammarCodes">
<value>42000,42001,42101,42102,42111,42112,42121,42122,42132value>
property>
<property name="duplicateKeyCodes">
<value>23001,23505value>
property>
<property name="dataIntegrityViolationCodes">
<value>22001,22003,22012,22018,22025,23000,23002,23003,23502,23503,23506,23507,23513value>
property>
<property name="dataAccessResourceFailureCodes">
<value>90046,90100,90117,90121,90126value>
property>
<property name="cannotAcquireLockCodes">
<value>50200value>
property>
<property name="customTranslations">
<bean class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">
<property name="errorCodes" value="23001,23505"/>
<property name="exceptionClass"
value="com.zgpeace.demodberrorcode.CustomDuplicatedKeyException"/>
bean>
property>
bean>
beans>
com.zgpeace.demodberrorcode.DemodberrorcodeApplicationTests
package com.zgpeace.demodberrorcode;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemodberrorcodeApplicationTests {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test(expected = CustomDuplicatedKeyException.class)
public void testThrowingCustomException() {
jdbcTemplate.execute("INSERT INTO FOO (ID, BAR) VALUES (1, 'A')");
jdbcTemplate.execute("INSERT INTO FOO (ID, BAR) VALUES (1, 'B')");
}
@Test
public void testThrowingException() {
jdbcTemplate.execute("INSERT INTO FOO (ID, BAR) VALUES (1, 'A')");
jdbcTemplate.execute("INSERT INTO FOO (ID, BAR) VALUES (1, 'B')");
}
}
注释:
com.zgpeace.demodberrorcode.CustomDuplicatedKeyException:
StatementCallback: Unique index or primary key violation:
"PRIMARY KEY ON PUBLIC.FOO(ID) [1, 'A']"; SQL statement:
INSERT INTO FOO (ID, BAR) VALUES (1, 'B') [23505-199];
nested exception is org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException:
Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.FOO(ID) [1, 'A']"; SQL statement:
INSERT INTO FOO (ID, BAR) VALUES (1, 'B') [23505-199]
恭喜你,学会了SpringBoot的JDBC异常自定义错误码处理。
代码下载:
https://github.com/zgpeace/Spring-Boot2.1/tree/master/db/demodberrorcode
https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#dao
https://github.com/geektime-geekbang/geektime-spring-family/tree/master/Chapter%202/errorcode-demo