来自触发器的异常映射 - spring-boot 2.4.x + jOOQ

Unexpected mapping of exception from trigger - spring-boot 2.4.x + jOOQ

我们正在使用 spring-boot 和 spring-boot-starter-jooq。对于一些复杂的约束检查,使用触发器会引发特定消息的错误。异常被持久层捕获并转化为业务异常

上次 spring 引导版本 2.4.x 中的行为已更改。例如带有 scherma 的 hsqldb:

CREATE TABLE tab1 (
    K INT PRIMARY KEY
)^;

CREATE TRIGGER trig1 BEFORE INSERT ON tab1
BEGIN ATOMIC
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'some error';
END^;

和插入 table 的代码:

    @Transactional
    public void withTriggerException() {
        create.insertInto(DSL.table("tab1"))
                .set(DSL.field("k"), 1)
                .execute();
    }

抛出异常的类型和消息与spring-boot版本不同。

2.3.6, 2.3.9

org.springframework.jdbc.UncategorizedSQLException:jOOQ;未分类 SQL SQL 异常 [插入 tab1 (k) 值 (cast(? as int))]; SQL状态[45000];错误代码 [5800];一些错误;嵌套异常是 java.sql.SQLException: 一些错误

2.4.0、2.4.1、2.4.2

java.lang.NullPointerException: 空

2.4.3

org.jooq.exception.DataAccessException: SQL [insert into tab1 (k) values (?)];未指定的 RuntimeException

    at org.jooq_3.14.7.HSQLDB.debug(Unknown Source) ~[na:na]
    at org.jooq.impl.Tools.translate(Tools.java:2892) ~[jooq-3.14.7.jar:na]
    at org.jooq.impl.DefaultExecuteContext.exception(DefaultExecuteContext.java:730) ~[jooq-3.14.7.jar:na]
    at org.springframework.boot.autoconfigure.jooq.JooqExceptionTranslator.handle(JooqExceptionTranslator.java:83) ~[spring-boot-autoconfigure-2.4.3.jar:2.4.3]
    at org.springframework.boot.autoconfigure.jooq.JooqExceptionTranslator.exception(JooqExceptionTranslator.java:55) ~[spring-boot-autoconfigure-2.4.3.jar:2.4.3]
    at org.jooq.impl.ExecuteListeners.exception(ExecuteListeners.java:274) ~[jooq-3.14.7.jar:na]
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:390) ~[jooq-3.14.7.jar:na]
    at org.jooq.impl.AbstractDelegatingQuery.execute(AbstractDelegatingQuery.java:119) ~[jooq-3.14.7.jar:na]
    at com.example.demo.FooDAO.withTriggerException(DemoApplication.java:38) ~[classes/:na]
...

该行为已在 hsqldb 上重现,但在 PostgreSQL 上相同。另一个错误(重复键、外键等)正在按预期工作。

可以通过 spring-boot 2.4.x?

从触发器中获取错误消息(示例中的“某些错误”)

您可能 运行 遇到这个问题:

关于 Spring 中的不兼容变化的一些背景,在 jOOQ 中产生了这种 NPE 回归,可以在这里看到:

修复应该在 Spring Boot 2.5.0 和 2.4.3 中可用:

您应该能够使用 DataAccessException.getCause(Class) 从 jOOQ 的 DataAccessException 访问 JDBC SQLException,例如

exception.getCause(SQLException.class);

但可能有更好的方法让 Spring 异常 t运行slator 直接为您提供实际原因。