コラボレーションの実行時に、データベース (関連データベースなど) から情報を取得する必要があることがあります。データベースの情報を取得または変更するには、その表を照会します。照会は、データベースに送信して実行させる、通常は SQL (Structured Query Language) ステートメント形式の要求です。表 51 に、データベースでの照会の実行に関する手順を示します。
照会の実行作業 | 詳細 | |
---|---|---|
1. | データベースへの接続 (CwDBConnection オブジェクト) を取得します。 | "接続の取得" |
2. | CwDBConnection オブジェクトを使用して、データベース内で照会の送信とトランザクションの管理を行います。 | "照会の実行""トランザクションの管理" |
3. | 接続を解放します。 | "接続の解放" |
データベースの照会を行うには、最初に BaseCollaboration クラスの getDBConnection() メソッドを使用してデータベースへの接続を取得する必要があります。
取得する接続を識別するには、この接続が含まれる接続プールの名前を指定します。
特定の接続プールのすべての接続は、同じデータベースに対して行われます。接続プール内の接続の数は、接続プール構成の一部として決定されます。照会対象のデータベースの接続が含まれる接続プールの名前を決定する必要があります。
図 77 では、getDBConnection() への呼び出しが、CustDBConnPool 接続プール内の接続に関連付けられたデータベースへの接続を取得します。
CwDBConnection connection = getDBConnection("CustDBConnPool");
getDBConnection() 呼び出しは、connection 変数内の CwDBConnection オブジェクトを戻します。このオブジェクトを使用すると、接続に関連付けられたデータベースにアクセスできます。
表 52 に、CwDBConnection クラスのメソッドを使用して SQL 照会を実行する方法を示します。
表 52. CwDBConnection メソッドの使用による SQL 照会の実行
照会のタイプ | 説明 | CwDBConnection メソッド |
---|---|---|
静的照会 | SQL ステートメントは、テキストとしてデータベースに送信されます。 | executeSQL() |
準備済み照会 | 初回の実行後、SQL ステートメントは、コンパイルされた実行可能形式で保管されます。これにより、後続の実行時に、このプリコンパイル形式が使用できます。 | executePreparedSQL() |
ストアード・プロシージャー | SQL ステートメントおよび条件ロジックが含まれるユーザー定義のプロシージャー | executeSQL()executePreparedSQL() executeStoredProcedure() |
executeSQL() メソッドは、静的照会を実行するためにデータベースへ送信します。
静的照会は、ストリングとしてデータベースに送信される SQL ステートメントです。このデータベースがこのストリングを解析し、結果の SQL ステートメントを実行します。このセクションでは、executeSQL() を使用して以下の種類の SQL 照会をデータベースに送信する方法について説明します。
SQL ステートメント SELECT は、1 つ以上の表のデータを照会します。SELECT ステートメントをデータベースに送信して実行させるには、SELECT のストリング表記を引き数として executeSQL() メソッドに指定します。例えば、executeSQL() への次の呼び出しは、customer 表から 1 列の値の SELECT を送信します。
connection.executeSQL( "select cust_id from customer where active_status = 1");
また、executeSQL() メソッドの 2 番目の形式を使用して、パラメーターを持つ SELECT ステートメントを送信することもできます。例えば、executeSQL() に対する以下の呼び出しにより、前の例と同じ操作が行われます。ただし、この場合、アクティブ状況がパラメーターとして SELECT ステートメントに渡されます。
Vector argValues = new Vector(); String active_stat = "1"; argValues.add( active_stat ); connection.executeSQL( "select cust_id from customer where active_status = ?", argValues);
SELECT ステートメントは、データベースの表からデータを行として戻します。
各行は、SELECT の WHERE 文節の条件と一致するデータの 1 行を示します。各行には、SELECT ステートメントが指定した列の値が含まれます。戻されたデータは、これらの行および列による 2 次元配列として表示できます。
戻されたデータにアクセスする手順は、以下のとおりです。
表 53 に、戻された照会データの行にアクセスするための CwDBConnection クラスのメソッドを示します。
列にアクセスするための操作 | CwDBConnection メソッド |
---|---|
行があるかどうかのチェック | hasMoreRows() |
1 行のデータを取得 | nextRow() |
hasMoreRows() メソッドを使用して、戻された行のループを制御します。 hasMoreRows() が false を戻したら、行のループを終了します。1 行のデータを取得するには、nextRow() メソッドを使用します。このメソッドは、選択された列の値を Java Vector オブジェクトの要素として戻します。
これにより、Enumeration クラスを使用して、列の値に個別にアクセスできます。
Vector クラスと Enumeration クラスの両方が java.util パッケージ内にあります。
表 54 に、戻された照会行の列にアクセスするための Java メソッドを示します。
列にアクセスするための操作 | Java メソッド |
---|---|
列の数の確認 | Vector.size() |
Enumeration に対する Vector のキャスト | Vector.elements() |
列があるかどうかのチェック | Enumeration.hasMoreElements() |
1 列のデータの取得 | Enumeration.nextElement() |
hasMoreElements() メソッドを使用して、列の値のループを制御します。 hasMoreElements() が false を戻したら、列のループを終了します。列の値を取得するには、nextElement() メソッドを使用します。
以下のコード・サンプルは、顧客情報が格納されたデータベースへの接続である CwDBConnection クラスのインスタンスを取得します。次に、SELECT ステートメントを実行します。これにより、顧客 ID 20987 の会社名「CrossWorlds」の単一列が含まれる 1 行が戻されます。
CwDBConnection connectn = null; Vector theRow = null; Enumeration theRowEnum = null; String theColumn1 = null; try { // Obtain a connection to the database connectn = getDBConnection("sampleConnectionPoolName"); } catch(CwDBConnectionFactoryException e) { System.out.println(e.getMessage()); throw e; } // Test for a resulting single-column, single-row, result set try { // Send the SELECT statement to the database connectn.executeSQL( "select company_name from customer where cust_id = 20987"); // Loop through each row while(connectn.hasMoreRows()) { // Obtain one row theRow = connectn.nextRow(); int length = 0; if ((length = theRow.size())!= 1) { return methodName + "Expected result set size = 1," + " Actual result state size = " + length; } // Get column values as an Enumeration object theRowEnum = theRow.elements(); // Verify that column values exist if (theRowEnum.hasMoreElements()) { // Get the column value theColumn1 = (String)theRowEnum.nextElement(); if (theColumn1.equals("CrossWorlds")==false) { return "Expected result = CrossWorlds," + " Resulting result = " + theColumn1; } } } } // Handle any exceptions thrown by executeSQL() catch(CwDBSQLException e) { System.out.println(e.getMessage()); }
以下の例は、複数の行を戻す SELECT ステートメントのコード・フラグメントを示します。各行には、顧客 ID および関連会社名の 2 列が含まれます。
CwDBConnection connectn = null; Vector theRow = null; Enumeration theRowEnum = null; Integer theColumn1 = 0; String theColumn2 = null; try { // Obtain a connection to the database connectn = getDBConnection("sampleConnectionPoolName"); } catch(CwDBConnectionFactoryException e) { System.out.println(e.getMessage()); throw e; } // Code fragment for multiple-row, multiple-column result set. // Get all rows with the specified columns, where the // specified condition is satisfied try { connectn.executeSQL( "select cust_id, company_name from customer where active_status = 1"); // Loop through each row while(connectn.hasMoreRows()) { // Obtain one row theRow = connectn.nextRow(); // Obtain column values as an Enumeration object theRowEnum = theRow.elements(); int length = 0; if ((length = theRow.size()) != 2) { return "Expected result set size = 2," + " Actual result state size = " + length; } // Verify that column values exist if (theRowEnum.hasMoreElements()) { // Get the column values theColumn1 = ((Integer)theRowEnum.nextElement()).intValue(); theColumn2 = (String)theRowEnum.nextElement(); } } } catch(CwDBSQLException e) { System.out.println(e.getMessage()); }
データベースの表のデータを変更する SQL ステートメントには、以下が含まれます。
これらのステートメントの 1 つを静的照会としてデータベースに送信して実行させるには、ステートメントのストリング表記を引き数として executeSQL() メソッドに指定します。例えば、executeSQL() に対する以下の呼び出しにより、現在の接続に関連付けられたデータベースの abc 表に対する 1 行の INSERT が送信されます。
connection.executeSQL("insert into abc values (1, 3, 6)");
UPDATE または INSERT ステートメントの場合、getUpdateCount() メソッドを使用して、変更または追加されたデータベースの表の行数を確認できます。
詳細については、"トランザクションの管理"を参照してください。
以下の両方の 条件が満たされていれば、executeSQL() メソッドを使用してストアード・プロシージャー呼び出しを実行できます。
ストアード・プロシージャーが OUT パラメーターを使用する場合は、それを実行するために executeStoredProcedure() を使用する必要があります。
executeSQL() メソッドは、ストアード・プロシージャー呼び出しに対する準備済みステートメント保管しません。このため、例えば、ループ内で同じストアード・プロシージャーを複数回呼び出す場合、executeSQL() を使用すると、準備済みステートメントを保管するメソッド executePreparedSQL() または executeStoredProcedure() を呼び出す場合より処理が遅くなることがあります。
詳細については、"ストアード・プロシージャーの実行"を参照してください。
executePreparedSQL() メソッドは、準備済み照会を実行するためにデータベースへ送信します。
準備済み照会は、データベースによる実行可能形式にすでにプリコンパイルされている SQL ステートメントです。executePreparedSQL() は、初めてデータベースに照会を送信するときに照会をストリングとして送信します。データベースは、この照会を受信し、文字列を解析して実行可能形式にコンパイルし、その結果の SQL ステートメントを実行します (executeSQL() に対する操作と同様)。ただし、データベースはこの SQL ステートメントのコンパイル済み形式を executePreparedSQL() に戻し、このメソッドがこのステートメントをメモリーに保管します。このコンパイル済み SQL ステートメントを、準備済みステートメントと呼びます。
これと同じ照会が後で実行されるときには、executePreparedSQL() は、この照会に対して準備済みステートメントがすでに存在するかどうかを最初にチェックします。準備済みステートメントが存在する場合、executePreparedSQL() は、照会ストリングの代わりにこれをデータベースに送信します。この後にこの照会が実行される場合、データベースはストリングを解析して準備済みステートメントを実行する必要がないため、処理がより効率的になります。
executePreparedSQL() を使用して、以下の種類の SQL 照会をデータベースに送信できます。
同じ SELECT ステートメントを複数回実行する必要がある場合は、executePreparedSQL() を使用してステートメントのプリコンパイル・バージョンを作成します。SELECT ステートメントを準備する場合は、以下の点に注意する必要があります。
同じ INSERT、UPDATE、または DELETE ステートメントを複数回実行する必要がある場合は、executePreparedSQL() を使用してステートメントのプリコンパイル・バージョンを作成します。再実行する SQL ステートメントは、実行するたびに正確に同じでなくても、準備済みステートメントの利点を利用できます。SQL ステートメントのパラメーターを使用して、ステートメントの実行のたびに情報を動的に提供できます。
図 78 のコード・フラグメントは、employee 表に 50 行を挿入します。executePreparedSQL() は、初めて呼び出されるときに、INSERT ステートメントのストリング・バージョンをデータベースに送信します。これにより、このデータベースは、これを解析し、実行し、その実行可能形式である準備済みステートメントを戻します。INSERT ステートメントが実行される次の 49 回 (すべての INSERT の実行が成功であると仮定) では、executePreparedSQL() は、準備済みステートメントが存在することを認識し、この準備済みステートメントをデータベースに送信して実行させます。
CwDBConnection connection; Vector argValues = new Vector(); argValues.setSize(2); int emp_id = 1; int emp_id = 2000; for (int = 1; i < 50; i++) { argValues.set(0, new Integer(emp_id)); argValues.set(1, new Integer(emp_num)); try { // Send the INSERT statement to the database connection.executePreparedSQL( "insert into employee (employee_id, employee_number) values (?, ?)", argValues); // Increment the argument values emp_id++; emp_num++ } catch(CwDBSQLException e) { System.out.println(e.getMessage()); } }
データベースを変更する SQL ステートメントを再実行する場合、トランザクション・プログラミング・モデルに応じてトランザクションを処理する必要があります。詳細については、"トランザクションの管理"を参照してください。
以下の両方の 条件が満たされていれば、executePreparedSQL() メソッドを使用してストアード・プロシージャー呼び出しを実行できます。
ストアード・プロシージャーが OUT パラメーターを使用する場合は、それを実行するために executeStoredProcedure() を使用する必要があります。
executePreparedSQL() メソッドは、ストアード・プロシージャー呼び出しに対する準備済みステートメントをメモリーに保管します。このため、ストアード・プロシージャーを 1 回のみ呼び出す場合、executePreparedSQL() を使用すると、準備済みステートメントを保管しないメソッド executeSQL() を使用してストアード・プロシージャーを呼び出す場合より多くのメモリーが使用されることがあります。
詳細については、"ストアード・プロシージャーの実行"を参照してください。
ストアード・プロシージャーは、SQL ステートメントおよび条件ロジックが含まれるユーザー定義のプロシージャーです。ストアード・プロシージャーは、データと共にデータベースに格納されます。
表 55 に、ストアード・プロシージャーを呼び出すための CwDBConnection クラスのメソッドを示します。
ストアード・プロシージャーを呼び出す方法 | CwDBConnection メソッド | 使用 |
---|---|---|
データベースに CALL ステートメントを送信し、ストアード・プロシージャーを実行します。 | executeSQL() | OUT パラメーターがなく、一度のみ 実行するストアード・プロシージャーを呼び出す方法。 |
| executePreparedSQL() | OUT パラメーターがなく、複数回 実行するストアード・プロシージャーを呼び出す方法。 |
ストアード・プロシージャーの名前およびパラメーターの配列を指定し、プロシージャー呼び出しを作成し、これをデータベースに送信して実行させます。 | executeStoredProcedure() | OUT パラメーターがある任意のストアード・プロシージャーを呼び出す方法。 |
ストアード・プロシージャーは、1 行または複数行の形式でデータを戻すことができます。
この場合、同じ Java メソッド (hasMoreRows() や nextRow() など) を使用して、SELECT ステートメントによって戻されたデータの場合と同じように、戻された照会結果の行にアクセスします。
詳細については、"データを戻す静的照会の実行 (SELECT)"を参照してください。
表 55 のように、どのメソッドを使用してストアード・プロシージャーを呼び出すかは、以下によって決まります。
OUT パラメーターは、ストアード・プロシージャーがこれを介して値を呼び出しコードに戻すパラメーターです。ストアード・プロシージャーが OUT パラメーターを使用する場合、executeStoredProcedure() を使用してストアード・プロシージャーを呼び出す必要があります 。
executeStoredProcedure() メソッドは、ストアード・プロシージャーのコンパイル済みバージョンを保管します。このため、例えば、ループ内で同じストアード・プロシージャーを複数回呼び出す場合、executeStoredProcedure() を使用すると、データベースがプリコンパイル済みバージョンを再使用できるため、executeSQL() より処理が速くなることがあります。
以下のセクションでは、executeSQL() メソッドと executeStoredProcedure() メソッドを使用してストアード・プロシージャーを呼び出す方法を説明します。
OUT パラメーターがない ストアード・プロシージャーを呼び出すには、CwDBConnection の以下のメソッドのいずれかを使用できます。
このプロシージャーは、ストリングとしてデータベースに送信され、ここで、実行される前に準備済みステートメントにコンパイルされます。この準備済みステートメントは、保管されません。このため、1 回のみ呼び出す必要があるストアード・プロシージャーの場合は executeSQL() が役に立ちます。
このプロシージャー呼び出しは、初回の呼び出し時にデータベースに送信されます。これにより、準備済みステートメントが作成され実行されます。ただし、データベースはこの準備済みステートメントを executePreparedSQL() に送信し、このメソッドがこのステートメントをメモリーに保管します。このため、例えば、ループ内などで複数回呼び出す必要があるストアード・プロシージャーにはexecutePreparedSQL() が役に立ちます。
これらいずれかのメソッドを使用してストアード・プロシージャーを呼び出すには、ストアード・プロシージャーおよび引き数を含む CALL ステートメントのストリング表記をメソッドの引き数として指定します。
図 79 では、executeSQL() への呼び出しが、setOrderCurrDate() ストアード・プロシージャーを実行するための CALL ステートメントを送信します。
図 79. executeSQL() でのストアード・プロシージャーの呼び出し
connection.executeSQL("call setOrderCurrDate(345698)");
図 79 で、connection 変数は、getDBConnection() メソッドへの前の呼び出しから取得した CwDBConnection オブジェクトです。executeSQL() を使用して、setOrderCurrDate() ストアード・プロシージャーを実行できます。これは、その単一引き数が IN パラメーターである、つまり、その値がストアード・プロシージャーのみ に送信されるためです。このストアード・プロシージャーには OUT パラメーターがありません。
パラメーター配列を受け入れる executeSQL() または executePreparedSQL() の形式を使用して、その引き数値をストアード・プロシージャーに渡すことができます。ただし、これらのメソッドを使用して、OUT パラメーターを使用するストアード・プロシージャーを呼び出すことはできません。このようなストアード・プロシージャーを実行するには、executeStoredProcedure() を使用する必要があります。詳細については、"executeStoredProcedure() でのストアード・プロシージャーの呼び出し"を参照してください。
connection.executeSQL("begin myproc(...); end;");
executeStoredProcedure() メソッドは、OUT パラメーターを使用するストアード・プロシージャーを含む、任意のストアード・プロシージャーを実行できます。このメソッドは、executePreparedSQL() の場合と同じように、ストアード・プロシージャー呼び出しに対する準備済みステートメントを保管します。このため、executeStoredProcedure() は、複数回実行されるストアード・プロシージャー呼び出しのパフォーマンスを向上できます。
executeStoredProcedure() メソッドを使用してストアード・プロシージャーを呼び出す手順は、以下のとおりです。
パラメーターは、ストアード・プロシージャーに対して、またはストアード・プロシージャーから送信できる値です。
パラメーターのイン/アウト・タイプにより、ストアード・プロシージャーがパラメーター値を使用する方法が決まります。
CwDBStoredProcedureParam オブジェクトは、ストアード・プロシージャーの単一パラメーターを示します。表 56 は、CwDBStoredProcedureParam オブジェクトに含まれるパラメーター情報と、このパラメーター情報を検索および設定するメソッドを示します。
表 56. CwDBStoredProcedureParam オブジェクトのパラメーター情報
パラメーター情報 | CwDBStoredProcedureParam メソッド |
---|---|
パラメーター値 |
getValue()
|
パラメーターのイン/アウト・タイプ |
getParamType()
|
executeStoredProcedure() メソッドを使用してストアード・プロシージャーにパラメーターを渡す手順は、以下のとおりです。
CwDBStoredProcedureParam() コンストラクターを使用して、新規 CwDBStoredProcedureParam オブジェクトを作成します。
このコンストラクターに以下のパラメーター情報を渡すことにより、オブジェクトを初期化します。
Vector クラスの addElement() メソッドまたは add() メソッドを使用して、CwDBStoredProcedureParam オブジェクトを追加します。
executeStoredProcedure() メソッドは、ストアード・プロシージャーおよびそのパラメーターをデータベースに送信して実行させます。
例えば、以下のように、データベースに get_empno() ストアード・プロシージャーが定義されているとします。
create or replace procedure get_empno(emp_id IN number, emp_number OUT number) as begin select emp_no into emp_number from emp where emp_id = 1; end;
この get_empno() ストアード・プロシージャーには、次の 2 つのパラメーターがあります。
このため、PARAM_IN のイン/アウト・タイプ、およびストアード・プロシージャーに送信する適切な値を使用して、その関連 CwDBStoredProcedureParam オブジェクトを初期化する必要があります。
emp_id は (整数値を保持する) SQL NUMBER 型として宣言されるので、パラメーターの値は、整数値 Integer を保持する Java Object になります。
このパラメーターに対しては、ストアード・プロシージャーへ送信する empty CwDBStoredProcedureParam オブジェクトを作成します。このオブジェクトは、PARAM_OUT のイン/アウト・タイプを使用して初期化します。
ただし、このパラメーターにはダミーの Integer 値を入力します。ストアード・プロシージャーによる実行が終了したら、getValue() メソッドを使用してこの OUT パラメーターから戻された値を取得できます。
図 80 は、executeStoredProcedure() メソッドを使用して get_empno() ストアード・プロシージャーを実行し、65 という従業員 ID の従業員番号を取得します。
図 80. get_empno() ストアード・プロシージャーの実行
CwDBConnection connectn = null; try { // Get database connection connectn = getDBConnection("CustomerDBPool"); // Create parameter Vector Vector paramData = new Vector(2); // Create IN parameter for the employee id and add to parameter // vector paramData.add( new CwDBStoredProcedureParam(PARAM_IN, new Integer(65))); // Create dummy argument for OUT parameter and add to parameter // vector paramData.add( new CwDBStoredProcedureParam(PARAM_OUT, new Integer(0)); // Call the get_empno() stored procedure connectn.executeStoredProcedure("get_empno", paramData); // Get the result from the OUT parameter CwDBStoredProcedureParam outParam = (CwDBStoredProcedureParam) paramData.get(1); int emp_number = ((Integer) outParam.getValue().Intvalue(); }
ストアード・プロシージャーは、そのパラメーターを SQL データ型として処理します。SQL および Java データ型は同一ではない ため、executeStoredProcedure() メソッドは、これら 2 つのデータ型間でパラメーター値を変換する必要があります。IN パラメーターの場合、executeStoredProcedure() は、パラメーター値を Java データ型から SQL データ型に変換します。OUT パラメーターの場合、executeStoredProcedure() は、パラメーター値を SQL データ型から Java データ型に変換します。
executeStoredProcedure() メソッドは、JDBC データ型を内部で使用し、ストアード・プロシージャーに送受信されるパラメーター値を保持します。JDBC は、java.sql.Types クラスで汎用 SQL タイプの ID の集合を定義します。
これらのタイプは、最も一般的に使用される SQL タイプを示します。また、JDBC には、JDBC タイプから Java データ型への標準マッピングも用意されています。例えば、通常、JDBC INTEGER は Java int タイプにマッピングされます。
executeStoredProcedure() メソッドは、表 57 に示されているマッピングを使用します。
トランザクションは、1 単位として実行される操作ステップの集合です。
トランザクション内で実行されるすべての SQL ステートメントは、1 単位として成功または失敗します。このセクションでは、トランザクションの管理に関する以下の情報について説明します。
トランザクションに対するデータベース操作の実行ステップのグループ化は、トランザクション・ブラケットと呼ばれます。各接続には、以下のトランザクション・プログラミング・モデルの 1 つが関連付けられます。
コラボレーション・オブジェクトは実行時に、獲得する各接続に対して使用するトランザクション・プログラミング・モデルを決定します。デフォルトでは、コラボレーション・オブジェクトは、獲得するすべての 接続により、そのトランザクション・プログラミング・モデルとして暗黙的なトランザクション・ブラケットが使用されることを前提としています。デフォルトのトランザクション・プログラミング・モデルは、表 58 の任意の方法を使用してオーバーライドできます。
表 58. 接続のトランザクション・プログラミング・モデルのオーバーライド
BaseCollaboration.implicitDBTransactionBracketing() メソッドを使用して、接続が使用する現在のトランザクション・プログラミング・モデルを決定できます。このメソッドは、トランザクション・プログラミング・モデルが暗黙的なトランザクション・ブラケットであるかどうかを示す boolean 値を戻します。
接続のトランザクション・プログラミング・モデルにより、データベース・トランザクションのスコープの指定方法が決まります。このセクションの内容は次のとおりです。
InterChange Server は、すべてのコラボレーションのトランザクション管理を処理します。コラボレーションのビジネス・オブジェクトのすべてのアクションは、1 単位として完了するか、または完了しません。このため、InterChange Server は、ビジネス・プロセス全体を単一の暗黙的なトランザクションとして処理します。なんらかの操作が失敗した場合は、「未解決のフロー」ブラウザーを使用して、失敗したコラボレーションの処理方法を選択します。
接続が暗黙的なトランザクション・ブラケットを使用する場合、InterChange Server は、接続プールの接続に関連付けられた、外部データベースで実行された操作のトランザクション管理も処理します。コラボレーションがデータベース操作を実行する場合、これらのデータベース操作はコラボレーションのビジネス・オブジェクトの一部です。InterChange Server は、メイン・トランザクションのサブトランザクション (コラボレーションのビジネス・プロセス) である暗黙的なトランザクションとしてこれらのデータベース操作を処理します。このデータベース・サブトランザクションは、コラボレーションが接続を取得すると同時に開始されます。
ICS は、コラボレーションの実行が完了すると、サブトランザクションを暗黙的に終了します。
このデータベース・サブトランザクションの成功または失敗は、以下のように、メイン・トランザクションの成功または失敗によって決まります。
このロールバックが失敗すると、InterChange Server は CwDBTransactionException 例外をスローしてエラーを記録します。
コラボレーションが別のコラボレーションを直接呼び出す場合、最初のコラボレーションは親と呼ばれ、2 番目のコラボレーションは子と呼ばれます。親コラボレーションが子コラボレーションを呼び出す場合、InterChange Server は、子コラボレーションのトランザクションを別個に管理します。この子コラボレーションの成功または失敗は、親コラボレーションの成功または失敗とは関係ありません。子コラボレーションが失敗した場合、親コラボレーションはこの失敗の処理方法を決定できます。例えば、親コラボレーションも失敗する必要があると決定することも、その状態を修正または無視して実行を続行すると決定することもできます。
ただし、子コラボレーションの成功または失敗が親コラボレーションの成功または失敗と関係ないとしても、子が実行する暗黙的データベース・トランザクションについてはこのことが当てはまりません。暗黙的なトランザクション・ブラケットを使用するデータベース接続を介して子コラボレーションがデータベース操作を実行する場合、この子コラボレーションは親コラボレーションのトランザクションを継承します。
InterChange Server は、これらのデータベース操作を親コラボレーションのサブトランザクションとして処理します。つまり、以下のように、子コラボレーションの暗黙的データベース・サブトランザクションの最終トランザクション状態は、親 (またはトップレベル) コラボレーションの成功または失敗によって決まります。
InterChange Server は、親コラボレーションの成功または失敗が判別するまでは、サブトランザクションをコミットまたはロールバックしません。
この振る舞いにより、子コラボレーションが失敗し、親コラボレーションが実行の続行を選択した場合、InterChange Server は、子コラボレーションの暗黙的データベース・トランザクションをコミットします。
子トランザクションを処理するこのメソッドにより、コラボレーションの開発者は、結合セマンティクスを明示的に使用せずに、子から親へのトランザクション結合を実行できます。また、子データベース・トランザクションが子レベルでコミットまたはロールバックされた場合、開発者は、子が (明示的または暗黙的に) 開始したトランザクションを、親が開始したグローバル・ビジネス・プロセス・トランザクションに関連付けることはできません。
接続が明示的なトランザクション・ブラケットを使用する場合、ICS は、コラボレーション・テンプレートが各データベース・トランザクションのスコープを明示的に指定することを必要とします。コラボレーションの成功または失敗とは関係ないデータベース操作を実行する必要がある場合、明示的なトランザクション・ブラケットが役に立ちます。例えば、特定の表がアクセスされたことを示す監査を実行する必要がある場合、この監査は、表へのアクセスが成功と失敗のいずれであるかとは関係なく実行する必要があります。明示的なトランザクションにデータベース操作の監査が含まれる場合、これらの操作はコラボレーションの成功または失敗とは関係なく実行されます。
表 59 に、明示的なトランザクションのトランザクション境界を管理するための CwDBConnection クラスのメソッドを示します。
トランザクション管理操作 | CwDBConnection メソッド |
---|---|
新しいトランザクションを開始します。 | beginTransaction() |
トランザクションの実行時にデータベースに対して行われたすべての変更をコミット (保管) し、トランザクションを終了します。 | commit() |
トランザクションが現在アクティブかどうかを確認します。 |
inTransaction()
|
トランザクションの実行時に行われたすべての変更をロールバック (バックアウト) し、トランザクションを終了します。 | rollBack() |
明示的なトランザクションのトランザクション・スコープを指定する手順は、以下のとおりです。
トランザクションが失敗した原因となる条件を選択できます。失敗条件が満たされた場合は、条件をテストし、rollBack() を呼び出します。それ以外の場合は、commit() を呼び出してトランザクションを正常に終了します。
以下のコード・フラグメントは、CustDBConnPool の接続に関連付けられたデータベースの 3 つの表を更新します。これらの更新がすべて 成功した場合は、コード・フラグメントによって commit() メソッドでこれらの変更がコミットされます。トランザクション・エラーが発生した場合は、CwDBTransactionException 例外が生じ、コード・フラグメントによって rollback() メソッドが呼び出されます。
CwDBConnection connection = getDBConnection("CustDBConnPool", false); // Begin a transaction connection.beginTransaction(); // Update several tables try { connection.executeSQL("update table1...."); connection.executeSQL("update table2...."); connection.executeSQL("update table3...."); // Commit the transaction connection.commit(); } catch (CwDBSQLException e) { // Roll back the transaction if an executeSQL() call throws // an exception connection.rollback(); } // Release the database connection connection.release();
トランザクションが現在アクティブかどうかを判別するには、inTransaction() メソッドを使用します。
接続は、解放されると、その接続プールに戻され、ここでその他のコンポーネントが使用できるようになります。
データベースへの接続が解放される方法は、トランザクション・プログラミング・モデルによって決まります。このセクションの内容は次のとおりです。
ICS は、データベース・トランザクションを終了すると、暗黙的なトランザクション・ブラケットを使用する接続を自動的に解放します。ICS は、コラボレーション・オブジェクトが成功または失敗のいずれかを確認するまでデータベース・トランザクションを終了しません。つまり、ICS は、コラボレーションが実行を終了するときにこれらの接続を解放します。コラボレーションが正常に実行されると、ICS は、アクティブなデータベース・トランザクションを自動的にコミットします。
コラボレーションの実行が失敗 (例えば、catch ステートメントによって処理されない例外がスローされる場合) すると、ICS は、アクティブなトランザクションを自動的にロールバックします。
明示的なトランザクション・ブラケットを使用する接続の場合、接続は、以下のいずれかの状況で終了します。
CwDBConnection isActive() メソッドを使用すると、接続が解放されているかどうかを判別できます。
次のコード・フラグメントが示しているように、接続が解放されている場合は、isActive() が false を戻します。
if (connection.isActive()) connection.release();
この例外を明示的に処理しないと、アクティブなトランザクションも自動的にロールバックされます。トランザクションがアクティブかどうかは、inTransaction() メソッドを使用して判別できます。ICS は、使用しているトランザクション・プログラミング・モデルとは関係なく、接続を自動的に解放します。多くの場合、接続は明示的に解放する必要はありません。