データ・ソースにアクセスするアプリケーションでエラーを適切に処理することは、誤ったデータの取得や挿入を避けるためにも、アプリケーションとデータ・ソース間で不整合が発生するのを避けるためにも、特に重要です。この演習では、リレーショナル・データベースへのアクセス時に発生するエラーに対処するために使用可能な、いくつかのツールについて学習します。
このチュートリアルの例では、try ブロック内にデータ・アクセス・ステートメントを置くケースが多かったことにお気付きだと思います。
function execDropTable(status StatusRec inOut)
try
execute #sql{
DROP TABLE EGL.CUSTOMERTEMP
} ;
onException (exception SQLException)
ConditionHandlingLib.HandleException(status, exception);
end
end
try ブロックにコードを置くと、EGL はこのコードの実行を通常どおりに試みます。EGL でエラーが発生した場合、EGL は try ブロック内でコードの実行を停止し、try ブロックに残っているステートメントはすべてスキップして、直接 onException ブロックに移動します。onException ブロック内に、エラーからのリカバリー、問題の修正、またはログ・ファイルへのエラー情報の書き込みを行うためのコードを含めることができます。try ブロック内で EGL にエラーが生じると、エラー情報を提供する例外レコードも作成されます。このレコードは onException ブロックに渡されます。 onException ブロック内で、そのレコード内の情報を使用して、エラーの原因を判別し、リカバリーできます。 上記の例で、onException ブロックは、例外レコードを、エラーを処理する関数に渡します。
例外レコードは、エラー・タイプに応じて、いくつかのステレオタイプの 1 つを持っている可能性があります。 上記の例で、onException ブロックは、SQLException ステレオタイプを持つ例外レコードを必要とします。このステレオタイプは、SQL エラーおよびその他のリレーショナル・データベース用です。NULL 値の参照などの、異なるタイプのエラーが EGL で生じた場合は、異なるタイプの例外レコード (NULL 値の参照の場合は、NullValueException ステレオタイプを持つ例外レコード) が作成されます。
function execDropTable(status StatusRec inOut)
try
execute #sql{
DROP TABLE EGL.CUSTOMERTEMP
} ;
onException (exception SQLException)
ConditionHandlingLib.HandleException(status, exception);
onException (exception AnyException)
HandleOtherError(exception);
end
end
この例では、最初の onException ブロックで SQLException レコードが必要になり、2 番目のブロックで AnyException ステレオタイプが必要になります。この場合、EGL で SQL エラーが生じると、最初の onException ブロックが実行されます。別の種類のエラーであれば、2 番目のブロックが実行されます。AnyException ステレオタイプは、一般ユーザーの例外レコードのステレオタイプで、ステレオタイプに関係なく、どのようなエラーに応答する場合にも使用されます。例外レコードにはすべて、最低 2 つのフィールドがあります。 1 つはエラーのエラー・コードを示す messageID フィールドで、もう 1 つは問題の簡単な説明を示すメッセージ・フィールドです。ステレオタイプに応じて、例外レコードは他のフィールドを持つことがあります。例えば、SQLRecord ステレオタイプには、ステートメントのステータスについての CHAR(5) 値を保持する sqlState フィールドと DBMS からの INT 戻りコードを保持する sqlCode フィールドがあります。
無効な情報の受け渡し、存在しないレコードの削除または更新、あるいは、同じ主キーを持つレコードの追加を行って、例外処理を試してみることができます。次の例では、同じ ID 番号を持つ新規顧客レコードを、データベースに既存の行として追加することを試みます。この結果、主キーとの競合が発生し、EGL が SQLException 例外をスローします。
ほとんどのリレーショナル・データベースは、Derby も含め、リカバリー可能リソースです。 リカバリー可能リソースに変更を行う場合、コミットを発行し、その変更を保存してはじめて変更が永続的なものになります。例外が生じた場合も、このように、それらの変更をコミットする前にデータベースへの変更を元に戻すことができます。
例えば、新規顧客を追加し、顧客からの最初のオーダーに関するオーダー情報を入力するなど、データベースにいくつかの変更を行っているとします。これらの操作の一部が成功した後で別の部分が失敗した場合は、顧客が入力されてオーダーが入力されなかったり、オーダーが入力されて顧客が入力されなかったりすることがあります。この場合、次のようにして、ロールバックを onException ブロックに含めて、変更を元に戻し、データベースに不完全な情報が含まれないようにします。
Order added successfully. SQL exception EGL0504E message = EGL0504E ADD: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL070307095259210' defined on 'CUSTOMER'.[sqlstate:23505][sqlcode:20000] EGL0002I The error occurred in the exceptionHandlingTest program processing the main function. Performing rollback. The order was rolled back successfully.これで、exceptionHandlingTest.egl ファイルのコードが完成しました。 このファイル内にエラーがある場合 (赤の X 記号でマークされている場合) は、演習 7 で完成した exceptionHandlingTest.egl ファイルに記載されているファイルのコードと、作成したコードが一致していることを確認してください。
この演習では、SQL 操作で生じたエラーの処理について基本的なことを学習しました。問題を予測し、アプリケーションをリカバリーできるよう例外処理を提供することは非常に重要です。