Java - 找到异常的第一个原因

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1791610/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:40:58  来源:igfitidea点击:

Java - find the first cause of an exception

javaoracleexception-handlingora-00001

提问by Averroes

I need to check if an exception is caused by some database problem. I receive an Exception and check if its cause contains the "ORA" string and return that (something like "ORA-00001"). The problem here is that the exception I receive is nested inside other exceptions, so if I don't find out if it's an oracle exception, I have to check into the cause of that exception and so on. Is there a cleaner way to do this? Is there a way to know the first cause (the deep-nested exception) of a given exception?

我需要检查异常是否是由某些数据库问题引起的。我收到一个异常并检查其原因是否包含“ORA”字符串并返回(类似于“ORA-00001”)。这里的问题是我收到的异常嵌套在其他异常中,所以如果我没有发现它是否是 oracle 异常,我必须检查该异常的原因等等。有没有更干净的方法来做到这一点?有没有办法知道给定异常的第一个原因(深层嵌套异常)?

My current code looks like this:

我当前的代码如下所示:

private String getErrorOracle(Throwable e){
        final String ORACLE = "ORA";
        if (e.getCause() != null && e.getCause().toString().contains(ORACLE)){
            return e.getCause().toString();
        } else if(e.getCause() != null){
            return getErrorOracle(e.getCause());
        } else {
            return null;
        }
    }

采纳答案by James Black

Just traverse the exception chain until you get to an exception with no cause, and then just return that message, if you want the last one.

只需遍历异常链,直到遇到一个没有原因的异常,然后返回该消息(如果您想要最后一个)。

Your function will only get the first cause, if there is one.

如果有第一个原因,您的函数只会得到第一个原因。

You may want to look at finding the first cause in your package though, as the actual deepest one may be an oracle exception, which is helpful, but unless you can see where you created the problem, you will have a hard time fixing it.

不过,您可能想查看包中的第一个原因,因为实际最深的原因可能是 oracle 异常,这很有帮助,但除非您能看到问题在哪里产生,否则您将很难修复它。

回答by coolest_head

you can use the getStackTrace()from the Throwable class. This would give you the stack of StackTraceElements to work with. You can iterate through the StackTraceElements[] to find "ORA" string.

您可以使用Throwable 类中的getStackTrace()。这将为您提供要使用的 StackTraceElements 堆栈。您可以遍历 StackTraceElements[] 以查找“ORA”字符串。

Let me know if you need an example.

如果您需要示例,请告诉我。

回答by Karl

I think that any error that is thrown by oracle will be wrapped in a SQLException (somebody please correct me if wrong). Once you have accessed the SQLException you should be able to call

我认为 oracle 抛出的任何错误都将包含在 SQLException 中(如果错误,请有人纠正我)。访问 SQLException 后,您应该能够调用

getErrorCode() Retrieves the vendor-specific exception code for this SQLException object.

getErrorCode() 检索此 SQLException 对象的供应商特定异常代码。

Let me know if this works as I have never tried it :-)

让我知道这是否有效,因为我从未尝试过:-)

Karl

卡尔

回答by spork

If the exception being thrown is always going to be of a specific type, like OracleException, you can catch just that exception.

如果抛出的异常总是属于特定类型,例如 OracleException,则您可以只捕获该异常。

For example:

例如:

try {

    ...

} catch(OracleException oe) {

    ...

}

This would only apply if there are specific Oracle exceptions being thrown. I don't know much about Oracle, so before attempting this you will probably want to find out if that's what's happening.

这仅适用于抛出特定 Oracle 异常的情况。我对 Oracle 了解不多,因此在尝试此之前,您可能想知道这是否是正在发生的事情。

回答by JuanZe

You could improve your code checking for SQLException

您可以改进对SQLException的代码检查

import java.sql.SQLException;

private static final String ORACLE = "ORA";

public String doHandle(Throwable t) {
    if (t.getClass().isAssignableFrom(SQLException.class)) {
    SQLException e = (SQLException) t;
    int errCode = e.getErrorCode();
    String state = e.getSQLState();
    String msg = e.getMessage();
    if (msg.contains(ORACLE)) {
        return msg;
        }
    } else {
        if (t.getCause() != null) {
            return this.doHandle(t.getCause());
            }
        }
    return "";
}

Also, I think in Oracle "errCode" contains the number associated to ORA-nnnn

另外,我认为在 Oracle 中“errCode”包含与 ORA-nnnn 关联的数字

回答by vickirk

Probably a bit overkill for your usage but I think it is cleaner (and reusable)

对于您的使用来说可能有点矫枉过正,但我​​认为它更干净(并且可重复使用)

interface ThrowablePredicate {
    boolean accept(Throwable t);
}

public OracleErrorThrowablePredicate implements ThrowablePredicate {
    private static final ORA_ERR = "ORA";

    public boolean accept(Throwable t) {
        return t.toString().contains(ORA_ERR);
    }
}


public class CauseFinder {

   private ThrowablePredicate predicate;

   public CauseFinder(ThrowablePredicate predicate) {
      this.predicate = predicate;
   }

   Throwable findCause(Throwable t) {
      Throwable cause = t.getCause();

      return cause == null ? null 
         : predicate.accept(cause) ? cause : findCause(cause)
   }
}


// Your method
private String getErrorOracle(Throwable e){
    return new CauseFinder(new OracleErrorThrowablePredicate()).findCause(e);
}

回答by Cowan

In the interests of not reinventing the wheel, if you're using Apache Commons Lang, then look at ExceptionUtils.getRootCause().

为了不重新发明轮子,如果您使用的是Apache Commons Lang,请查看ExceptionUtils.getRootCause()

Is it worth including a library just for that? Maybe not. But if you already have it on your classpath, it's there for you, and note that it does some things that a 'naive' implementation might not do (e.g. deal with cycles in the cause chain... ugh!)

是否值得为此包括一个图书馆?也许不吧。但是如果你已经在你的类路径上有它,它就在你身边,并注意它做了一些“天真的”实现可能不会做的事情(例如处理原因链中的循环......呃!)

回答by Nándor Krácser

If you are already on Guavathan Throwables.getRootCause()comes to the rescue.

如果你已经在Guava 上,那么Throwables.getRootCause()就会派上用场。

回答by Fasiha

on 28-01-2015, i have unable to solve my problem with any of the above solution, so my recommendation is to use :

在 28-01-2015 上,我无法使用上述任何解决方案解决我的问题,所以我的建议是使用:

e.getMessage().toString();

Ps: i am using it on android.

Ps:我在安卓上使用它。