SQLExceptionを補足した時にチェーンされた例外
SQLExceptionを補足した時にチェーンされた例外をすべて見たかったんだけど、getNextExceptionで戻り値がnullになるまでループするのと、iteratorでループするのでは取得される例外が異なるみたい。https://docs.oracle.com/javase/jp/8/docs/api/java/sql/SQLException.html
... } catch (SQLException e) { for (Throwable t : e) { ... } }
... } catch (SQLException e) { for (SQLException sqle = e; sqle != null; sqle = sqle.getNextException()) { ... } }iteratorは単純にgetNextExceptionを反復してくれるのかと思っていたら、そうではなかった。
戻り値の型
まず、getNextExceptionとiteratorでは戻り値の型が違う。getNextExceptionの戻り値はSQLExceptionで、iteratorの戻り値はIterator<Throwable>になっている。
つまり、iteratorを使うと、SQLExceptionではない例外やエラーが取得される場合がある。
getNextException
setNextExceptionのAPIリファレンスには、以下のように書かれている。setNextException(SQLException ex)によってこのSQLExceptionオブジェクトにチェーンされた例外を取得します。
これは、まあ想定どおり。
iterator
iteratorのAPIリファレンスには、以下のように書かれている。チェーンされたSQLExceptionについてのイテレータを返します。イテレータは、各SQLExceptionとその基になる原因(存在する場合)を反復するために使用されます。
基になる原因と言っているので、Throwable.getCauseで取得される例外も返してくるということだろう。
なので
試しにsetNextExceptionとコンストラクタで原因例外を設定して、iteratorでループしてみると、こんな感じになる。try { SQLException e = new SQLException("SQLException1", new Exception("Exception1", new Exception("Exception0"))); e.setNextException(new SQLException("SQLException2", new Exception("Exception2"))); throw e; } catch (SQLException e) { for (Throwable t : e) { System.out.println("loop..."); System.out.println(t.getMessage()); } }
loop... SQLException1 loop... Exception1 loop... Exception0 loop... SQLException2 loop... Exception2
まず、getCauseで取得される原因例外をたどっていって、それがなくなったら、getNextExceptionで次のSQLExceptionを取得するという順番になっている。
SQLExceptionのgetErrorCodeやgetSQLStatを使いたい場合は、instanceofで分岐するしかないかなあ。
0 件のコメント:
コメントを投稿