Java Spring引导:处理从数据库触发器引发的异常

Java Spring引导:处理从数据库触发器引发的异常,java,spring,hibernate,spring-boot,spring-data-jpa,Java,Spring,Hibernate,Spring Boot,Spring Data Jpa,我需要阻止表中ceratin列的更新操作并显示消息。我正在使用liquibase来管理数据库模式。为了实现这一点,我使用了触发器函数和触发器,它们工作得很好 功能 CREATE OR REPLACE FUNCTION FN_BU_CATEGORY() RETURNS trigger LANGUAGE plpgsql AS $$BEGIN IF NEW.created_by <> OLD.created_by THEN RAISE EXCEPTION 'Not

我需要阻止表中ceratin列的更新操作并显示消息。我正在使用liquibase来管理数据库模式。为了实现这一点,我使用了触发器函数和触发器,它们工作得很好

功能

CREATE OR REPLACE FUNCTION FN_BU_CATEGORY() RETURNS trigger
   LANGUAGE plpgsql AS
$$BEGIN
   IF NEW.created_by <> OLD.created_by THEN
      RAISE EXCEPTION 'Not allowed to update the value of created_by';
   END IF;
   RETURN NEW;
END;$$;
@ExceptionHandler({PSQLException.class, GenericJDBCException.class, JpaSystemException.class})
public ResponseEntity<Problem> handleTriggerException(Exception ex, NativeWebRequest request) {
    Problem problem = Problem.builder()
        .withStatus(Status.BAD_REQUEST)
        .withDetail("Test Message " + ex.getMessage())
        .build();
    return create(ex, problem, request);
}

我正在使用
@ControllerAdvice
@ExceptionHandler
以及
PSQLException.class、genericjdbception.class、JpaSystemException.class来管理异常处理,我能够处理异常。为了验证功能,当我点击API来更新受限列的值时,触发器引发了异常,我可以在控制台中看到以下内容

handleTriggerException

CREATE OR REPLACE FUNCTION FN_BU_CATEGORY() RETURNS trigger
   LANGUAGE plpgsql AS
$$BEGIN
   IF NEW.created_by <> OLD.created_by THEN
      RAISE EXCEPTION 'Not allowed to update the value of created_by';
   END IF;
   RETURN NEW;
END;$$;
@ExceptionHandler({PSQLException.class, GenericJDBCException.class, JpaSystemException.class})
public ResponseEntity<Problem> handleTriggerException(Exception ex, NativeWebRequest request) {
    Problem problem = Problem.builder()
        .withStatus(Status.BAD_REQUEST)
        .withDetail("Test Message " + ex.getMessage())
        .build();
    return create(ex, problem, request);
}
问题是

当前,
ex.getMessage()
返回org.hibernate.exception.genericjdbception:无法执行语句

  • 如何获取触发器中描述的消息(即PSQLException:不允许更新) 创造的价值(由)
  • 如果我删除
    JpaSystemException
    ,handleTriggerException不再工作,为什么
环境:

框架:Spring Boot
ORM:Hibernate
数据库:Postgres 11


更新:

我尝试使用以下方法获取消息,但不幸的是,它们都返回相同的消息

System.out.println("1: " +ex.getCause());
System.out.println("2: " +ex.getMessage());
System.out.println("3: " +ex.getLocalizedMessage());
System.out.println("4: " +ex.fillInStackTrace());
System.out.println("5: " +ex.getStackTrace());

1: org.hibernate.exception.GenericJDBCException: could not execute statement
2: could not execute statement; nested exception is         org.hibernate.exception.GenericJDBCException: could not execute statement
3: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement
4: org.springframework.orm.jpa.JpaSystemException: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement    
5: [Ljava.lang.StackTraceElement;@6f3072be
@ExceptionHandler({PSQLException.class, GenericJDBCException.class, JpaSystemException.class})
public ResponseEntity<Problem> handleTriggerException(Exception ex, NativeWebRequest request) {

        Problem problem = Problem.builder()
            .withStatus(Status.BAD_REQUEST)
            .withDetail(ExceptionUtils.getRootCause(ex).getMessage())
            .build();
        return create(ex, problem, request);
}
与一起使用将显示根本原因消息

System.out.println("1: " +ex.getCause());
System.out.println("2: " +ex.getMessage());
System.out.println("3: " +ex.getLocalizedMessage());
System.out.println("4: " +ex.fillInStackTrace());
System.out.println("5: " +ex.getStackTrace());

1: org.hibernate.exception.GenericJDBCException: could not execute statement
2: could not execute statement; nested exception is         org.hibernate.exception.GenericJDBCException: could not execute statement
3: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement
4: org.springframework.orm.jpa.JpaSystemException: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement    
5: [Ljava.lang.StackTraceElement;@6f3072be
@ExceptionHandler({PSQLException.class, GenericJDBCException.class, JpaSystemException.class})
public ResponseEntity<Problem> handleTriggerException(Exception ex, NativeWebRequest request) {

        Problem problem = Problem.builder()
            .withStatus(Status.BAD_REQUEST)
            .withDetail(ExceptionUtils.getRootCause(ex).getMessage())
            .build();
        return create(ex, problem, request);
}
@ExceptionHandler({psqleexception.class,genericjdbception.class,JpaSystemException.class})
公共响应handleTriggerException(异常示例,NativeWebRequest请求){
Problem=Problem.builder()
.withStatus(状态错误请求)
.withDetail(ExceptionUtils.getRootCause(ex).getMessage())
.build();
返回创建(例如,问题,请求);
}

原因:
意味着您需要调用
getCause()
来获取底层异常。感谢@Andreas,我尝试了
getCause()
和其他方法,但不幸的是,它们都给出了相同的消息org.hibernate.exception.genericjdbception:无法执行语句。我已经相应地更新了问题。如果您转换为JdbcException或GenericJDBCException,那么您可以提取根sqlexception、错误代码或sql状态等信息。谢谢,@CodeScale,我已经使用
ExceptionUtils
谢谢,@Andreas解决了这个问题。谢谢你的提示。我可以使用
ExceptionUtils
getRootCause(throwable)
获取消息如果您指定了
ExceptionUtils
是什么,这个答案可能会更有用。