データベース照会の実行

マップの実行時に、データベース (リレーションシップ・データベースなど) から情報を取得する必要があることがあります。データベースの情報を取得または変更するには、その表を照会します。照会 は、データベースに送信して実行させる、通常は SQL (Structured Query Language) ステートメント形式の要求です。表 68 に、データベースでの照会の実行に関する手順を示します。

注:
IBM により JDBC でサポートされるすべての外部データベースに、Oracle シン・ドライバーや WebLogic ドライバーを使用してアクセスできます。データベースには、Oracle と Microsoft SQL Server を含みます。

表 68. 照会の実行手順
照会の実行作業 詳細情報の参照先
1. データベースへの接続 (CwDBConnection オブジェクト) を取得します。 "接続の取得"
2. CwDBConnection オブジェクトを使用して、照会を送信し、データベース内のトランザクションを管理します。 "照会の実行" "トランザクションの管理"
3. 接続を解放します。 "接続の解放"

接続の取得

データベースの照会を行うには、最初に BaseDLM クラスの getDBConnection() メソッドを使用してデータベースへの接続を取得する必要があります。 取得する接続を識別するには、この接続が含まれる接続プールの名前を指定します。

特定の接続プールのすべての接続は、同じデータベースに対して行われます。接続プール内の接続の数は、接続プール構成の一部として決定されます。照会対象のデータベースの接続が含まれる接続プールの名前を決定する必要があります。

要確認:
接続は、InterChange Server Express がブートしたときに開かれるか、新しい接続プールが構成されたときに動的に開かれます。このため、目的のデータベースに対する接続が含まれる接続プールは、接続を要求するマップ・インスタンスが実行される前に構成する必要があります。IBM System Manager 内に接続プールを構成します。

図 92 では、getDBConnection() の呼び出しにより、CustDBConnPool 接続プール内の接続に関連するデータベースへの接続が取得されます。

図 92. 接続プールからの接続の取得

CwDBConnection connection = 
  getDBConnection("CustDBConnPool");
 

getDBConnection() 呼び出しにより CwDBConnection オブジェクトが connection 変数に戻されます。その後これを使用して、接続に関連するデータベースにアクセスできます。

ヒント:
getDBConnection() メソッドは、接続のトランザクション・プログラミング・モデルを指定できる追加形式を提供します。詳細については、"トランザクションの管理"を参照してください。

照会の実行

表 69 に、CwDBConnection クラスのメソッドを使用して SQL 照会を実行する方法を示します。

表 69. CwDBConnection メソッドの使用による SQL 照会の実行
照会のタイプ 説明 CwDBConnection メソッド
静的照会 SQL ステートメントは、テキストとしてデータベースに送信されます。 executeSQL()
準備済み照会 初回の実行後、SQL ステートメントは、コンパイルされた実行可能形式で保管されます。これにより、後続の実行時に、このプリコンパイル形式が使用できます。 executePreparedSQL()
ストアード・プロシージャー SQL ステートメントおよび条件ロジックが含まれるユーザー定義のプロシージャー。 executeSQL()executePreparedSQL()
executeStoredProcedure()

静的照会の実行

executeSQL() メソッドにより、静的照会がデータベースに送信されて実行されます。 静的照会 は、ストリングとしてデータベースに送信される SQL ステートメントです。このデータベースがこのストリングを解析し、結果の SQL ステートメントを実行します。このセクションでは、executeSQL() を使用して以下の種類の SQL 照会をデータベースに送信する方法について説明します。

データを戻す静的照会の実行 (SELECT)

SQL ステートメント SELECT は、1 つ以上の表のデータを照会します。SELECT ステートメントをデータベースに送信して実行させるには、SELECT のストリング表記を引き数として executeSQL() メソッドに指定します。

例: executeSQL() への次の呼び出しにより、customer 表からの 1 つの列値を取得する SELECT が送信されます。

connection.executeSQL(
    "select cust_id from customer where active_status = 1");
 

注:
前述のコードでは、connection 変数は前の getDBConnection() メソッドの呼び出しで取得した CwDBConnection オブジェクトです (図 92 を参照)。

また、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 次元配列として表示できます。

ヒント:
SELECT ステートメントの構文は、アクセスする特定のデータベースに対して有効である必要があります。SELECT ステートメントの正確な構文については、データベース文書を確認してください。

戻されたデータにアクセスするには、次の手順を実行します。

  1. 1 行のデータを取得します。
  2. 列の値を 1 つずつ取得します。

表 70 に、戻された照会データの行にアクセスするための CwDBConnection クラスのメソッドを示します。

表 70.
行にアクセスするための CwDBConnection メソッド
行にアクセスするための操作 CwDBConnection メソッド
行があるかどうかのチェック hasMoreRows()
1 行のデータの取得 nextRow()

hasMoreRows() メソッドを使用して、戻された行のループを制御します。hasMoreRows() から false が戻されると、行ループが終了します。1 行のデータを取得するには、nextRow() メソッドを使用します。このメソッドは、選択された列の値を Java Vector オブジェクトの要素として戻します。 これにより、Enumeration クラスを使用して、列の値に個別にアクセスできます。 VectorEnumeration の両クラスは java.util パッケージに存在します。

表 71 に、戻された照会行の列にアクセスするための Java メソッドを示します。

表 71. 列の値にアクセスするための 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());
    }
 

注:
SELECT ステートメントでは、データベースの内容は変更されません。したがって、通常は SELECT ステートメントのトランザクション管理を行う必要はありません

データを変更する静的照会の実行

データベース表のデータを変更する SQL ステートメントには、以下が含まれます。

これらのステートメントの 1 つを静的照会としてデータベースに送信して実行させるには、executeSQL() メソッドの引き数として、ステートメントをストリング表記で指定します。

例: executeSQL() に対する以下の呼び出しにより、現在の接続に関連付けられたデータベースの abc 表に対する 1 行の INSERT が送信されます。

connection.executeSQL("insert into abc values (1, 3, 6)");
 

注:
前述のコードでは、connection 変数は前の getDBConnection() メソッドの呼び出しで取得した CwDBConnection オブジェクトです。

UPDATE または INSERT ステートメントの場合、getUpdateCount() メソッドを使用して、変更または追加されたデータベース表の行数を確認できます。

要確認:
INSERT、UPDATE、および DELETE ステートメントはデータベースの内容を変更するため、これらのステートメントに対してトランザクション管理の必要性を評価してください。 詳細については、"トランザクションの管理"を参照してください。

静的ストアード・プロシージャーの実行

以下の両方の 条件が満たされていれば、executeSQL() メソッドを使用してストアード・プロシージャー呼び出しを実行できます。

詳細については、"ストアード・プロシージャーの実行"を参照してください。

準備済み照会の実行

executePreparedSQL() メソッドにより、準備済み照会がデータベースに送信されて実行されます。 準備済み照会 は、データベースによる実行可能形式にすでにプリコンパイルされている SQL ステートメントです。executePreparedSQL() は、初めてデータベースに照会を送信するときに照会をストリングとして送信します。データベースは、この照会を受信し、ストリングを解析して実行可能形式にコンパイルし、その結果の SQL ステートメントを実行します (executeSQL() に対する操作と同様)。ただし、データベースはこの SQL ステートメントのコンパイル済み形式を executePreparedSQL() に戻し、このメソッドがこのステートメントをメモリーに格納します。このコンパイル済み SQL ステートメントは、準備済みステートメント と呼ばれます。

これと同じ照会が後で実行されるときには、executePreparedSQL() は、この照会に対して準備済みステートメントがすでに存在するかどうかを最初にチェックします。準備済みステートメントが存在する場合、executePreparedSQL() は、照会ストリングの代わりにこれをデータベースに送信します。この後にこの照会が実行される場合、データベースはストリングを解析して準備済みステートメントを実行する必要がないため、処理がより効率的になります。

executePreparedSQL() を使用して、以下の種類の SQL 照会をデータベースに送信できます。

データを戻す準備済み照会の実行 (SELECT)

同じ SELECT ステートメントを複数回実行する必要がある場合は、executePreparedSQL() を使用してステートメントのプリコンパイル・バージョンを作成します。SELECT ステートメントを準備する場合は、以下の点に注意する必要があります。

データを変更する準備済み照会の実行

同じ INSERT、UPDATE、または DELETE ステートメントを複数回実行する必要がある場合は、executePreparedSQL() を使用してステートメントのプリコンパイル・バージョンを作成します。再実行する SQL ステートメントは、実行するたびに正確に同じでなくても、準備済みステートメントの利点を利用できます。SQL ステートメントのパラメーターを使用して、ステートメントの実行のたびに情報を動的に提供できます。

図 93 のコード・フラグメントでは、employee 表に 50 行挿入します。executePreparedSQL() は、初めて呼び出されるときに、INSERT ステートメントのストリング・バージョンをデータベースに送信します。これにより、このデータベースは、これを解析し、実行し、その実行可能形式である準備済みステートメントを戻します。INSERT ステートメントが実行される次の 49 回 (すべての INSERT の実行が成功であると仮定) では、executePreparedSQL() は、準備済みステートメントが存在することを認識し、この準備済みステートメントをデータベースに送信して実行させます。

図 93. 準備済みステートメントへの引き数値の引き渡し

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());
       }
    }
 

ヒント:
通常、INSERT ステートメントの準備済みバージョンの実行により、アプリケーションのパフォーマンスが向上しますが、アプリケーションのメモリー・フットプリントは増加します。

データベースを変更する SQL ステートメントを再実行する場合、トランザクション・プログラミング・モデルに応じてトランザクションを処理する必要があります。詳細については、"トランザクションの管理"を参照してください。

注:
コードをわかりやすくするために、図 93 にはトランザクション管理が含まれていません

準備済みストアード・プロシージャーの実行

以下の両方の 条件が満たされていれば、executePreparedSQL() メソッドを使用してストアード・プロシージャー呼び出しを実行できます。

詳細については、"ストアード・プロシージャーの実行"を参照してください。

ストアード・プロシージャーの実行

ストアード・プロシージャー は、SQL ステートメントおよび条件ロジックが含まれるユーザー定義のプロシージャーです。ストアード・プロシージャーは、データとともにデータベースに格納されます。

注:
新しい関係を作成する場合、各関係表を保守するためにストアード・プロシージャーが作成されます。

表 72 に、ストアード・プロシージャーを呼び出す CwDBConnection クラスのメソッドを示します。

表 72.
ストアード・プロシージャーを呼び出す CwDBConnection メソッド
ストアード・プロシージャーの呼び出し方法 CwDBConnection メソッド 使用
データベースに CALL ステートメントを送信し、ストアード・プロシージャーを実行します。 executeSQL() OUT パラメーターを使用しない ストアード・プロシージャーを呼び出して、1 回のみ 実行するため。

executePreparedSQL() OUT パラメーターを使用しない ストアード・プロシージャーを呼び出して、複数回 実行するため。
ストアード・プロシージャーの名前およびパラメーターの配列を指定し、プロシージャー呼び出しを作成し、これをデータベースに送信して実行させます。 executeStoredProcedure() OUT パラメーターがある任意のストアード・プロシージャーを呼び出すため。

注:
JDBC メソッドを使用して、ストアード・プロシージャーを直接実行できます。しかし、CwDBConnection クラスで用意されているインターフェースは単純で、データベース・リソースを再使用するので、実行効率を向上させることができます。ストアード・プロシージャーを実行するには、CwDBConnection クラスのメソッドを使用してください。

ストアード・プロシージャーは、1 行または複数行の形式でデータを戻すことができます。 この場合は、SELECT ステートメントで戻されたデータに対してと同じ Java メソッド (hasMoreRows()nextRow() など) を使用して、照会から戻された行にアクセスします。 詳細については、"データを戻す静的照会の実行 (SELECT)"を参照してください。

表 72 に示す、どのメソッドを使用してストアード・プロシージャーを呼び出すかは、以下によって決まります。

次のセクションでは、executeSQL()executeStoredProcedure() メソッドを使用した、ストアード・プロシージャーの呼び出し方法について説明します。

OUT パラメーターがないストアード・プロシージャーの呼び出し

OUT パラメーターがない ストアード・プロシージャーを呼び出すには、CwDBConnection の以下のメソッドのいずれかを使用できます。

これらいずれかのメソッドを使用してストアード・プロシージャーを呼び出すには、メソッドの引き数として、ストアード・プロシージャーおよび引き数を含む CALL ステートメントをストリング表記で指定します。 図 94 では、executeSQL() の呼び出しにより、setOrderCurrDate() ストアード・プロシージャーを実行する CALL ステートメントが送信されます。

図 94. executeSQL() によるストアード・プロシージャーの呼び出し

connection.executeSQL("call setOrderCurrDate(345698)");
 

図 94 では、connection 変数は、getDBConnection() メソッドの前の呼び出しで取得した CwDBConnection オブジェクトです。executeSQL() を使用して、setOrderCurrDate() ストアード・プロシージャーを実行できます。これは、その単一引き数が IN パラメーターである、つまり、その値がストアード・プロシージャーのみ に送信されるためです。このストアード・プロシージャーは、どの OUT パラメーターも使用しません

パラメーター配列を受け入れる executeSQL() または executePreparedSQL() の形式を使用して、その引き数値をストアード・プロシージャーに渡すことができます。ただし、これらのメソッドを使用して、OUT パラメーターを使用するストアード・プロシージャーを呼び出すことはできません。このようなストアード・プロシージャーを実行するには、executeStoredProcedure() を使用する必要があります。詳細については、"executeStoredProcedure() によるストアード・プロシージャーの呼び出し"を参照してください。

注:
CwDBConnection .executeSQL() メソッドを使用して ODBC を介して Oracle ストアード PL/SQL オブジェクトを呼び出す場合は、匿名 PL/SQL ブロックを使用します。以下は、受け入れ可能なフォーマットを示します (ストアード・プロシージャー名は myproc です)。
connection.executeSQL("begin myproc(...);
  end;");
 

executeStoredProcedure() によるストアード・プロシージャーの呼び出し

executeStoredProcedure() メソッドは、OUT パラメーターを使用するストアード・プロシージャーを含む、任意のストアード・プロシージャーを実行できます。このメソッドは、executePreparedSQL() の場合と同じように、ストアード・プロシージャー呼び出しに対する準備済みステートメントを保管します。このため、executeStoredProcedure() は、複数回実行されるストアード・プロシージャー呼び出しのパフォーマンスを向上できます。

executeStoredProcedure() メソッドを使用してストアード・プロシージャーを呼び出す手順

executeStoredProcedure() メソッドを使用してストアード・プロシージャーを呼び出すには、以下の手順を行います。

  1. 実行するストアード・プロシージャーの名前を String で指定します。
  2. CwDBStoredProcedureParam オブジェクトの Vector パラメーター配列を作成します。これにより、各ストアード・プロシージャーのイン/アウト・パラメーター・タイプやパラメーター値などのパラメーター情報が指定されます。

パラメーター は、ストアード・プロシージャーに対して、またはストアード・プロシージャーから送信できる値です。

パラメーターのイン/アウト・タイプにより、ストアード・プロシージャーがパラメーター値を使用する方法が決まります。

CwDBStoredProcedureParam オブジェクトで、ストアード・プロシージャーの単一パラメーターを記述します。表 73 に、CwDBStoredProcedureParam オブジェクトに含まれる情報と、このパラメーター情報を検索して設定するメソッドを示します。


表 73. CwDBStoredProcedureParam オブジェクトのパラメーター情報
パラメーター情報 CwDBStoredProcedureParam メソッド
パラメーター値 getValue()
パラメーターのイン/アウト・タイプ getParamType()

executeStoredProcedure() メソッドを使用してストアード・プロシージャーにパラメーターを渡す手順

executeStoredProcedure() メソッドを使用してストアード・プロシージャーにパラメーターを渡す手順は、以下のとおりです。

  1. CwDBStoredProcedureParam オブジェクトを作成して、パラメーター情報を保持します。

    CwDBStoredProcedureParam() コンストラクターを使用して、新しい CwDBStoredProcedureParam オブジェクトを作成します。

    このコンストラクターに以下のパラメーター情報を渡すことにより、オブジェクトを初期化します。

  2. 各ストアード・プロシージャーのパラメーターについて、ステップ 1 を繰り返します。
  3. すべてのストアード・プロシージャーのパラメーターを保持するのに十分な要素を持つ Vector オブジェクトを作成します。
  4. 初期化された CwDBStoredProcedureParam オブジェクトをパラメーター Vector オブジェクトに追加します。

    Vector クラスの addElement() または add() メソッドを使用して、CwDBStoredProcedureParam オブジェクトを追加します。

  5. すべての CwDBStoredProcedureParam オブジェクトを作成し、これらを Vector パラメーター配列に追加したら、このパラメーター配列を 2 番目の引き数として executeStoredProcedure() メソッドに渡します。

    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 つのパラメーターがあります。

図 95 は、executeStoredProcedure() メソッドで get_empno() ストアード・プロシージャーを実行して、従業員 ID が 65 の従業員番号を取得します。

図 95. 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();
    }
 

ヒント:
Java Vector オブジェクトは、ゼロから始まる配列です。前のコードでは、Vector 配列がゼロから始まるため、Vector パラメーター配列からこの OUT パラメーターの値にアクセスするために、get() 呼び出しは、インデックス値 1 を指定します。

ストアード・プロシージャーは、そのパラメーターを 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() メソッドは、表 74 に示すマッピングを使用します。

表 74.
Java と JDBC データ型とのマッピング
Java データ型 JDBC データ型
String CHAR、VARCHAR、または LONGVARCHAR
Integer、int INTEGER
Long BIGINT
Float、float REAL
Double、double DOUBLE
java.math.BigDecimal NUMERIC
Boolean、boolean BIT
java.sql.Date DATE
java.sql.Time TIME
java.sql.Timestamp TIMESTAMP
java.sql.Clob CLOB
java.sql.Blob BLOB
byte[] BINARY、VARBINARY、または LONGVARBINARY
Array ARRAY
Struct STRUCT

トランザクションの管理

トランザクション は、1 単位として実行される操作ステップの集合です。 トランザクション内で実行されるすべての SQL ステートメントは、1 単位として成功または失敗します。このセクションでは、トランザクションの管理に関する以下の情報について説明します。

トランザクション・プログラミング・モデルの判別

トランザクションに対するデータベース操作の実行ステップのグループ化は、トランザクション・ブラケット と呼ばれます。各接続には、以下のトランザクション・プログラミング・モデルの 1 つが関連付けられます。

マップ・インスタンスは実行時に、獲得する各接続に対して使用するトランザクション・プログラミング・モデルを決定します。デフォルトでは、マップは獲得するすべての 接続により、そのトランザクション・プログラミング・モデルとして暗黙的なトランザクション・ブラケットが使用されることを前提としています。 デフォルトのトランザクション・プログラミング・モデルは、表 75 の任意の方法を使用してオーバーライドできます。

表 75. 接続のトランザクション・プログラミング・モデルのオーバーライド
オーバーライドするトランザクション・プログラミング・モデル 実行するアクション
特定のマップ・インスタンスで取得されたすべての接続に関する トランザクション・プログラミング・モデルの指定 「マップ・プロパティー」ダイアログの「一般」タブの「暗黙的なデータベース・トランザクション」チェック・ボックスを選択または選択解除します。 Service Manager の「マップ・プロパティー」ウィンドウでこのプロパティーを設定することもできます。
特定の接続に関する トランザクション・プログラミング・モデルの指定 boolean 値を入力し、(この接続のみに対して) 目的のトランザクション・プログラミング・モデルを getDBConnection() メソッドのオプションの 2 番目の引き数として指定します。

以下の getDBConnection() 呼び出しは、ConnPool 接続プールから取得された接続に明示的なトランザクション・ブラケットを指定します。

conn = getDBConnection("ConnPool",
     false);
 

BaseDLM.implicitDBTransactionBracketing() メソッドを使用して、接続が使用する現在のトランザクション・プログラミング・モデルを決定できます。このメソッドは、トランザクション・プログラミング・モデルが暗黙的なトランザクション・ブラケットであるかどうかを示す boolean 値を戻します。

トランザクション・スコープの指定

接続のトランザクション・プログラミング・モデルにより、データベース・トランザクションのスコープの指定方法が決まります。このセクションの内容は次のとおりです。

暗黙的なトランザクション・ブラケットでのトランザクション・スコープ

InterChange Server Express は、単一の暗黙的なトランザクションでのマップのアクションを処理します。接続が暗黙的なトランザクション・ブラケットを使用する場合、InterChange Server は、接続プールの接続に関連付けられた、外部データベースで実行された操作のトランザクション管理も処理します。マップでデータベース操作を実行する場合、InterChange Server Express はこれらのデータベース操作を、メイン・トランザクション (マップ) のサブトランザクションである暗黙的な操作としても処理します。このデータベース・サブトランザクションは、マップが接続を取得すると直ちに開始されます。 InterChange Server Express は、マップの実行が完了すると、このサブトランザクションを暗黙的に終了します。

このデータベース・サブトランザクションの成功または失敗は、以下のように、マップの成功または失敗により異なります。

明示的なトランザクション・ブラケットでのトランザクション・スコープ

接続で明示的なトランザクション・ブラケットを使用すると、InterChange Server Express はマップ定義を予期して、各データベース・トランザクションのスコープを明示的に指定します。マップの成功または失敗とは関係ないデータベース操作を実行する必要がある場合、明示的なトランザクション・ブラケットが役に立ちます。

例: 特定の表がアクセスされたことを示す監査を実行する必要がある場合、この監査は、テーブルへのアクセスが成功と失敗のいずれであるかとは関係なく実行する必要があります。明示的なトランザクションにデータベース操作の監査が含まれる場合、これらの操作はマップの成功または失敗とは関係なく実行されます。

表 76 は、明示的なトランザクションのトランザクション境界を管理するための CwDBConnection クラスのメソッドを示します。

表 76.
明示的なトランザクションを管理するための CwDBConnection メソッド
トランザクション管理操作 CwDBConnection メソッド
新しいトランザクションを開始します。 beginTransaction()
トランザクションの実行時にデータベースに対して行われたすべての変更をコミット (保管) し、トランザクションを終了します。 commit()
トランザクションが現在アクティブかどうかを確認します。 inTransaction()
トランザクションの実行時に行われたすべての変更をロールバック (バックアウト) し、トランザクションを終了します。 rollBack()

明示的なトランザクションのトランザクション・スコープ指定手順

明示的なトランザクションのトランザクション・スコープを指定するには、次の手順を実行します。

  1. beginTransaction() メソッドを呼び出して、トランザクションを開始します。
  2. beginTransaction() の呼び出しとトランザクションの終了との間の 単位として成功または失敗する必要があるすべての SQL を実行します。
  3. 以下のいずれかの方法により、トランザクションを終了します。

    トランザクションが失敗した原因となる条件を選択できます。失敗条件が満たされた場合は、条件をテストし、rollBack() を呼び出します。あるいは、commit() を呼び出して、トランザクションを正常終了します。

要確認:
beginTransaction() を使用して明示的なトランザクションの開始を指定しない 場合、データベースは、各 SQL ステートメントを個別トランザクションとして実行します。beginTransaction() を組み込むが、接続が解放される前に commit() または rollback() を使用してデータベース・トランザクションの終了を指定しない 場合、マップが成功したかどうかに基づいて InterChange Server Express により暗黙的にトランザクションが終了されます。 マップが成功の場合、InterChange Server Express は、このデータベース・トランザクションをコミットします。マップが成功しなかった 場合、InterChange Server Express はデータベース・トランザクションを暗黙的にロールバックします。マップが成功かどうかにかかわらず、InterChange Server Express は警告を記録します。

以下のコード・フラグメントは、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() メソッドを使用します。

重要:
beginTransaction()commit()、および rollback() メソッドは、接続で明示的なトランザクション・ブラケットを使用する場合にのみ 使用します。接続で暗黙的なトランザクション・ブラケットを使用する場合は、これらのメソッドを使用すると、CwDBTransactionException 例外が発生します。

接続の解放

接続は、解放されると、その接続プールに戻され、ここでその他のコンポーネントが使用できるようになります。

データベースへの接続が解放される方法は、トランザクション・プログラミング・モデルによって決まります。このセクションの内容は次のとおりです。

暗黙的なトランザクション・ブラケットでの接続の解放

InterChange Server Express は、データベース・トランザクションを終了すると、暗黙的なトランザクション・ブラケットを使用する接続を自動的に解放します。InterChange Server Express は、マップが成功または失敗のいずれかを確認するまでデータベース・トランザクションを終了しません。つまり、InterChange Server Express は、マップ・インスタンスが実行を終了するときにこれらの接続を解放します。マップが正常に実行されると、InterChange Server Express は、アクティブなデータベース・トランザクションを自動的にコミットします。 マップの実行が失敗 (例えば、catch ステートメントによって処理されない例外がスローされる場合) すると、InterChange Server Express は、アクティブなトランザクションを自動的にロールバックします。

明示的なトランザクション・ブラケットでの接続の解放

明示的なトランザクション・ブラケットを使用する接続の場合、接続は、以下のいずれかの状況で終了します。

CwDBConnection.isActive() メソッドを使用して、接続が解放されたかどうかを判別できます。

接続が解放されると、次のコード・フラグメントに示すように、isActive() により false が戻されます。

if (connection.isActive())
    connection.release();
 

重要:
トランザクションが現在アクティブな場合は、release() メソッドを使用しないでください。暗黙的なトランザクション・ブラケットの場合、InterChange Server Express は、マップが成功または失敗のいずれかを確認するまでデータベース・トランザクションを終了しません。このため、暗黙的なトランザクション・ブラケットを使用する接続にこのメソッドを使用すると、CwDBTransactionException 例外が発生します。

この例外を明示的に処理しないと、アクティブなトランザクションも自動的にロールバックされます。inTransaction() メソッドを使用すると、トランザクションがアクティブであるかどうかを判別できます。InterChange Server Express は、使用しているトランザクション・プログラミング・モデルとは関係なく、接続を自動的に解放します。多くの場合、接続は明示的に解放する必要はありません。

Copyright IBM Corp. 2004