如何循环通过 Exception getCause()来查找带有详细信息的根原因

我正在尝试调用 saveOrUpdate()在休眠中保存数据。因为列有唯一的索引,所以当我通过 Eclipse 调试器查看时,它会抛出 ConstraintViolationException

因为在向表插入数据时,不同异常的根原因可能不同。
我想知道,如何循环/遍历 getCause()来检查异常的根本原因及其消息。

更新:
感谢大家的友好回应,事情是我想输出如下图:
enter image description here
我需要进入 信息场。
(非常抱歉,我的问题不能说得更清楚。)

谢谢。

105203 次浏览

Are you asking for something like this?

Throwable cause = originalException;
while(cause.getCause() != null && cause.getCause() != cause) {
cause = cause.getCause();
}

or am I missing something?

The Apache ExceptionUtils provide the following method:

Throwable getRootCause(Throwable throwable)

as well as

String getRootCauseMessage(Throwable th)
} catch (Exception ex) {
while (ex.getCause() != null)
ex = ex.getCause();
System.out.println("Root cause is " + ex.getMessage());
}

Were you expecting something more complicated?

In APACHE; the implementation is like below.

The highlight is list.contains(throwable) == false

public static Throwable getRootCause(final Throwable throwable) {
final List<Throwable> list = getThrowableList(throwable);
return list.size() < 2 ? null : (Throwable)list.get(list.size() - 1);
}


public static List<Throwable> getThrowableList(Throwable throwable) {
final List<Throwable> list = new ArrayList<Throwable>();
while (throwable != null && list.contains(throwable) == false) {
list.add(throwable);
throwable = ExceptionUtils.getCause(throwable);
}
return list;
}

I normally use the implementation below instead of Apache's one.

Besides its complexity, Apache's implementation returns null when no cause is found, which force me to perform an additional check for null.

Normally when looking for an exception's root/cause I already have a non-null exception to start with, which is for all intended proposes is the cause of the failure at hand, if a deeper cause can't be found.

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


while(null != (cause = result.getCause())  && (result != cause) ) {
result = cause;
}
return result;
}

Using java 8 Stream API, this can be achieved by:

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

Note that this code is not immune to exception cause loops and therefore should be avoided in production.

Guava's Throwables provides the following methods:

Throwable getRootCause(Throwable throwable)

as well as

String getStackTraceAsString(Throwable throwable)

Try this, you can put this function in a kind of Util class:

public static Throwable getRootException(Throwable exception){
Throwable rootException=exception;
while(rootException.getCause()!=null){
rootException = rootException.getCause();
}
return rootException;
}

Example of usage :

catch(MyException e){
System.out.println(getRootException(e).getLocalizedMessage());
}

Source : How to get the root exception of any exception

Recursively:

public static Throwable getRootCause(Throwable e) {
if (e.getCause() == null) return e;
return getRootCause(e.getCause());
}