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

写作时间:2019-08-18
Spring Boot: 2.1 ,JDK: 1.8, IDE: IntelliJ IDEA

说明

一致异常层级结构(Consistent Exception Hierarchy):
Spring提供了以DataAccessException为异常基类。所有的数据库操作异常信息都会包括在异常基类中,不用担心异常信息的丢失.

DataAccessException继承图解

易筋SpringBoot 2.1 | 第十八篇:SpringBoot的JDBC异常_第1张图片

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

易筋SpringBoot 2.1 | 第十八篇:SpringBoot的JDBC异常_第2张图片

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,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。

易筋SpringBoot 2.1 | 第十八篇:SpringBoot的JDBC异常_第3张图片

设置日志打印格式化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




<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>

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/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

你可能感兴趣的:(易实战Sprint,Boot,2.1)