web-dev-qa-db-ja.com

Java-例外の最初の原因を見つける

例外の原因がデータベースの問題かどうかを確認する必要があります。例外を受け取り、その原因に「ORA」文字列が含まれているかどうかを確認し、それを返します(「ORA-00001」のようなもの)。ここでの問題は、受け取る例外が他の例外の中にネストされているため、それがOracleの例外であるかどうかわからない場合は、その例外の原因などを確認する必要があるということです。これを行うためのよりクリーンな方法はありますか?特定の例外の最初の原因(深い入れ子の例外)を知る方法はありますか?

私の現在のコードは次のようになります:

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;
        }
    }
34
Averroes

原因のない例外に到達するまで例外チェーンをトラバースし、最後のメッセージが必要な場合はそのメッセージを返すだけです。

関数は、最初の原因がある場合にのみそれを取得します。

ただし、実際の最も深い原因はOracleの例外である可能性があるため、パッケージで最初の原因を見つけることを検討することもできますが、これは役に立ちますが、問題の発生場所を確認できないと、問題の修正に苦労します。

15
James Black

ホイールを再発明しないために、 Apache Commons Lang を使用している場合は、 ExceptionUtils.getRootCause() を確認してください。

そのためだけにライブラリを含める価値はありますか?そうでないかもしれない。しかし、クラスパスにすでにそれがある場合、それはあなたのためにあり、「素朴な」実装が行わないかもしれないいくつかのことを行うことに注意してください(たとえば、原因チェーンのサイクルに対処します...うーん!)

82
Cowan

あなたがすでに Guava を使用している場合、 Throwables.getRootCause() よりも役に立ちます。

16

おそらくあなたの使用法には少々やりすぎですが、私はそれがよりクリーン(そして再利用可能)だと思います

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);
}
4
vickirk

OracleによってスローされたエラーはSQLExceptionでラップされると思います(誰かが間違っている場合は修正してください)。 SQLExceptionにアクセスすると、次を呼び出すことができるはずです。

getErrorCode()このSQLExceptionオブジェクトのベンダー固有の例外コードを取得します。

これが私が試したことがないのでうまくいくかどうか教えてください:-)

カール

2
Karl

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 "";
}

また、Oracleでは「errCode」にORA-nnnnに関連付けられた番号が含まれていると思います

2
JuanZe

throwableクラスの getStackTrace() を使用できます。これにより、使用するStackTraceElementのスタックが得られます。 StackTraceElements []を反復処理して、「ORA」文字列を見つけることができます。

例が必要な場合はお知らせください。

0
coolest_head