寫作時間:2019-08-18
Spring Boot: 2.1 ,JDK: 1.8, IDE: IntelliJ IDEA
說明
一致異常層級結構(Consistent Exception Hierarchy):
Spring提供了以DataAccessException爲異常基類。所有的數據庫操作異常信息都會包括在異常基類中,不用擔心異常信息的丟失.
DataAccessException繼承圖解
Spring怎麼認識錯誤碼的
通過SQLErrorCodeSQLExceptionTranslator解析錯誤碼
ErrorCode 定義
- org/springframework/jdbc/support/sql-error-codes.xml
- Classpath 下的 sql-error-codes.xml
SQLErrorCodes 源碼位置
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;
...
}
註釋:
- databaseProductNames 數據庫名字
- badSqlGrammarCodes 語法錯誤碼
- duplicateKeyCodes 重複主鍵
錯誤碼配置信息
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,42132</value>
</property>
<property name="duplicateKeyCodes">
<value>23001,23505</value>
</property>
<property name="dataIntegrityViolationCodes">
<value>22001,22003,22012,22018,22025,23000,23002,23003,23502,23503,23506,23507,23513</value>
</property>
<property name="dataAccessResourceFailureCodes">
<value>90046,90100,90117,90121,90126</value>
</property>
<property name="cannotAcquireLockCodes">
<value>50200</value>
</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
ANSI - American National Standards Institute
Support classes to provide ANSI color output.
src > main > resources > application.yml
spring:
output:
ansi:
enabled: always
創建表Foo
路徑 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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="H2" class="org.springframework.jdbc.support.SQLErrorCodes">
<property name="badSqlGrammarCodes">
<value>42000,42001,42101,42102,42111,42112,42121,42122,42132</value>
</property>
<property name="duplicateKeyCodes">
<value>23001,23505</value>
</property>
<property name="dataIntegrityViolationCodes">
<value>22001,22003,22012,22018,22025,23000,23002,23003,23502,23503,23506,23507,23513</value>
</property>
<property name="dataAccessResourceFailureCodes">
<value>90046,90100,90117,90121,90126</value>
</property>
<property name="cannotAcquireLockCodes">
<value>50200</value>
</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>
Controller UnitTesst
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')");
}
}
註釋:
- 方法testThrowingCustomException()運行通過,因爲自定義異常,沒有處理重複主鍵的問題。
- 方法testThrowingException() 報重複主鍵異常
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/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