如何通过Exception getCause()循环查找具有详细消息的根本原因

agp*_*gpt 63 java plsql exception

我试图saveOrUpdate()在休眠中调用来保存数据.由于列具有唯一索引,因此ConstraintViolationException当我通过Eclipse调试器查看时它会抛出.

由于在将数据插入表时,根本原因可能因异常而异.
我想知道,如何循环/遍历getCause()以检查异常的根本原因及其消息.

更新:
感谢大家的回复,我希望输出如下图所示:
在此输入图像描述
我需要访问 detailMessage字段.
(我真的很抱歉,如果不能让我的问题更清楚.)

谢谢.

ret*_*eto 82

Apache ExceptionUtils提供以下方法:

Throwable getRootCause(Throwable throwable) 
Run Code Online (Sandbox Code Playgroud)

以及

String getRootCauseMessage(Throwable th) 
Run Code Online (Sandbox Code Playgroud)

  • 您可以在Guava的[Throwables](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Throwables.html)中找到类似的东西:`getRootCause(Throwable )`和`getStackTraceAsString(Throwable)` (17认同)

Leg*_*gna 63

我通常使用下面的实现而不是Apache的实现.

除了它的复杂性,Apache的实现在没有找到原因时返回null,这迫使我执行额外的null检查.

通常在查找异常的根/原因时我已经有一个非空的异常开始,如果无法找到更深层的原因,那么对于所有预期的建议都是导致失败的原因.

Throwable getCause(Throwable e) {
    Throwable cause = null; 
    Throwable result = e;

    while(null != (cause = result.getCause())  && (result != cause) ) {
        result = cause;
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为这样的答案应该由提问者和社区提供,而不是只有工具或lib推荐的答案. (6认同)
  • 我在上面提供的实现是保护您远离一步深度的循环链接异常,这意味着当异常链到自身时e = e.getCause()(我遇到的最常见且唯一的情况).然而,apache的实现将真正保护您的代码免受任何深度的循环异常链的影响e = e.getCause().getCause()... etc .. .getCause(); (6认同)
  • 确实很有帮助!:) 谢谢 ! (2认同)

Spa*_*ker 17

使用java 8 Stream API,可以通过以下方式实现:

Optional<Throwable> rootCause = Stream.iterate(exception, Throwable::getCause)
                                      .filter(element -> element.getCause() == null)
                                      .findFirst();
Run Code Online (Sandbox Code Playgroud)

请注意,此代码不能免除异常原因循环,因此应在生产中避免使用.

  • 我喜欢这段代码,但无法理解为什么在生产中应该避免它,有例子吗? (3认同)

mor*_*ano 8

你在问这样的事吗?

Throwable cause = originalException;
while(cause.getCause() != null && cause.getCause() != cause) {
    cause = cause.getCause();
}
Run Code Online (Sandbox Code Playgroud)

还是我错过了什么?

  • 异常基本上是数据库类型异常.所以上面的循环进入无限循环. (6认同)

sch*_*rer 7

GuavaThrowables提供以下方法:

Throwable getRootCause(Throwable throwable)
Run Code Online (Sandbox Code Playgroud)

以及

String getStackTraceAsString(Throwable throwable)
Run Code Online (Sandbox Code Playgroud)