易筋SpringBoot 2.1 | 第十八篇:SpringBoot的JDBC異常

寫作時間:2019-08-18
Spring Boot: 2.1 ,JDK: 1.8, IDE: IntelliJ IDEA

說明

一致異常層級結構(Consistent Exception Hierarchy):
Spring提供了以DataAccessException爲異常基類。所有的數據庫操作異常信息都會包括在異常基類中,不用擔心異常信息的丟失.

DataAccessException繼承圖解

Spring怎麼認識錯誤碼的

通過SQLErrorCodeSQLExceptionTranslator解析錯誤碼

ErrorCode 定義

  1. org/springframework/jdbc/support/sql-error-codes.xml
  2. 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;

...
}

註釋:

  1. databaseProductNames 數據庫名字
  2. badSqlGrammarCodes 語法錯誤碼
  3. 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')");
  }

}


註釋:

  1. 方法testThrowingCustomException()運行通過,因爲自定義異常,沒有處理重複主鍵的問題。
  2. 方法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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章