この項では、TimesTen Javaアプリケーションで発生するエラーの検出、識別および処理について説明します。
TimesTenにより返されるエラーのリストおよびエラーが発生した場合の対処方法については、『Oracle TimesTen In-Memory Database APIおよびSQLリファレンス・ガイド』の警告およびエラーに関する章を参照してください。
内容は次のとおりです。
TimesTenでは、致命的エラー、致命的でないエラーまたは警告が返される場合があります。
致命的エラーとは、リカバリするまでデータ・ストアにアクセスできなくなるエラーのことです。致命的エラーが発生すると、すべてのデータ・ストアの接続を切断する必要があります。それ以後の処理は完了されません。致命的エラーは、TimesTenのエラー・コード846および994で示されます。これらのエラーの処理は、標準的なエラーの処理とは異なります。具体的には、コードによってトランザクションをロールバックし、データ・ストアからの接続を切断する必要があります。
致命的エラーが発生した場合、TimesTenは、次の完全なクリーンアップおよびリカバリ・プロシージャを実行します。
致命的ではないエラーには、一意制約に違反しているINSERTなどの単純なエラーが含まれます。また、一部のアプリケーション障害およびプロセス障害も、致命的ではないエラーに含まれます。
TimesTenでは、致命的ではないエラーも、通常のエラー処理プロセスによって返されます。また、エラーの検出および識別はアプリケーションで行う必要があります。
致命的ではないエラーによってデータ・ストアに影響が出た場合、エラーが返されることがあり、アプリケーションで適切に対処する必要があります。プロセスのクラッシュなどの場合はエラーが返されないため、失敗したプロセスのトランザクションが自動的にロールバックされます。
アプリケーションでは、その処理を変更するか、または障害が発生した1つ以上のトランザクションをロールバックすることによって、致命的ではないエラーに対処できます。詳細は、「失敗したトランザクションのロールバック」を参照してください。
予期しない状態が発生した場合、TimesTenは警告を返します。たとえば、次の状況が発生した場合、TimesTenは警告を発行します。
コールのたびに返される可能性があるすべてのエラーと警告を確認してレポートする必要があります。これによって、開発およびデバッグの時間および労力が大幅に削減されます。データ・ストアのアクセス時にエラーが1つ以上ある場合は、SQLExceptionオブジェクトが発生し、警告メッセージが1つ以上ある場合は、SQLWarningオブジェクトが発生します。1回のコールで複数のエラーまたは警告(あるいはその両方)が返されることがあるため、アプリケーションでは、返されたSQLExceptionオブジェクトまたはSQLWarningオブジェクトにすべてのエラーまたは警告をレポートする必要があります。
SQLExceptionオブジェクトまたはSQLWarningオブジェクトのリンク連鎖では、複数のエラーまたは警告が返されます。例2.12および例2.13に、すべてのエラーと警告をレポートするために返されたSQLExceptionオブジェクトとSQLWarningオブジェクトのリストを繰り返し実行する方法を示します。
このメソッドは、リンクされたSQLExceptionオブジェクトのすべての例外の内容を印刷します。
static int reportSQLExceptions(SQLException ex) { int errCount = 0; if (ex != null) { errStream.println("\n--- SQLException caught ---"); ex.printStackTrace(); while (ex != null) { errStream.println("SQL State: " + ex.getSQLState()); errStream.println("Message: " + ex.getMessage()); errStream.println("Error Code: " + ex.getErrorCode()); errCount ++; ex = ex.getNextException(); errStream.println(); } } return errCount; }
このメソッドは、リンクされたSQLWarningオブジェクトのすべての例外の内容を印刷します。
static int reportSQLWarnings(SQLWarning wn) { int warnCount = 0; while (wn != null) { errStream.println("\n--- SQL Warning ---"); errStream.println("SQL State: " + wn.getSQLState()); errStream.println("Message: " + wn.getMessage()); errStream.println("Error Code: " + wn.getErrorCode()); // is this a SQLWarning object or a DataTruncation object? if (wn instanceof DataTruncation) { DataTruncation trn = (DataTruncation) wn; errStream.println("Truncation error in column: " + trn.getIndex()); } warnCount++; wn = wn.getNextWarning(); errStream.println(); } return warnCount; }
特定のSQLの状態またはTimesTenエラー・コードに対応する必要がある場合があります。SQLException.getSQLStateを使用してSQL99 SQL状態エラー文字列を返したり、SQLException.getErrorCodeを使用してTimesTenエラー・コードを返すことができます。例2.14を参照してください。
TimesTenのデモでは、デモ・スキーマをロードしてから実行する必要があります。ODBCエラーS0002およびTimesTenエラー907が検出されると、次のcatch文により、デモ・スキーマがロードまたは更新されていないというアラートがユーザーに発行されます。
catch (SQLException ex) { if (ex.getSQLState().equalsIgnoreCase("S0002")) { errStream.println("\nError: The table xyz.customer does not exist.\n\t Please run ttIsql -f input0.dat to initialize the database."); } else if (ex.getErrorCode() == 907) { errStream.println("\nError: Attempting to insert a row with a duplicate primary key.\n\tPlease rerun ttIsql -f input0.dat to reinitialize the database."); }TimesTenVendorCodeインタフェースを使用すると、番号ではなく名前によって、エラーを検出できます。
次に例を示します。
ex.getErrorCode() == com.timesten.jdbc.TimesTenVendorCode.TT_ERR_KEYEXISTSこれは、次の文と同じです。
ex.getErrorCode() == 907エラーの名前と番号のマッピングについては、「TimesTenVendorCode」を参照してください。
デッドロックまたはタイムアウトの状態からリカバリする場合など、Connection.rollback()メソッドを使用して明示的にトランザクションをロールバックする場合があります。
次に例を示します。
try { if (con != null && !con.isClosed()) { // Rollback any transactions in case of errors if (retcode != 0) { try { System.out.println("\nEncountered error. Rolling back transaction"); con.rollback(); } catch (SQLException ex) { reportSQLExceptions(ex); } } System.out.println("\nClosing the connection\n"); con.close(); }SYS.MONITOR表のXACT_ROLLBACKS列は、ロールバックされたトランザクションの数を示します。
トランザクションのロールバックによってリソースが消費され、結果的にトランザクション全体が無駄になってしまいます。不要なロールバックを回避するには、可能なかぎり、競合が発生しないようにアプリケーションを設計(「最適なロック方法の選択」)し、送信前にアプリケーションまたは入力データをチェックしてエラーを検出する必要があります。