Database Connector の例 - Mule 4

Database 用 Anypoint Connector (Database Connector) の例は、データベース接続の設定、データベースの照会、ストアドプロシージャーの実行、DDL ステートメントの実行、スクリプトの実行、データベーストランザクションの実行、一括操作の使用、カスタムデータ型の定義に役立ちます。

  • データベース接続の設定

    一般的なデータベースと汎用データベースの両方に接続します。また、グローバルデータソースへの接続、JDBC ドライバーの設定、接続プーリングの設定、TNS を使用した Oracle データベースへの接続を行うようにコネクタを設定します。

  • ​データベースの照会
    データベースからデータを照会する ​Select​ 操作を設定します。

  • ​データの挿入、更新、削除
    データを管理するように ​Insert​、​Update​、​Delete​ 操作を設定します。

  • ​ストアドプロシージャーの実行
    input​、​output​、および ​input-output​ パラメーターを組み合わせる ​Stored Procedure​ 操作を設定します。また、ストアドプロシージャーの日付を設定します。

  • UDT を使用する Oracle ストアドプロシージャーのコール

    UDT を入力および出力パラメーターとして使用する Oracle データベースストアドプロシージャーをコールする ​Stored procedure​ 操作を設定します。また、​createStruct​ および ​createArray​ DataWeave 関数を使用してアプリケーションデータをカスタム型にマップします。

  • ​DDL ステートメントの実行
    テーブルや他のデータ構造内のデータを作成または変更する DDL ステートメントを実行する ​Execute DDL​ 操作を設定します。

  • ​一括操作の実行
    各入力パラメーターが 1 つの値のみを取る場合に使用する ​Bulk insert​、​Bulk update​、​Bulk delete​ 操作を設定します。

  • ​スクリプトの実行
    スクリプトを 1 つのステートメントとして実行する ​Execute script​ 操作を設定します。

  • ​カスタムデータ型の定義
    特定の接続プロバイダーに接続している場合に使用するカスタムデータ型を定義します。

  • ​データベーストランザクションの実行
    データベース操作をトランザクションのコンテキストで実行します。

データベースのクエリ

Database Connector を使用してデータベース操作を設定する場合、データベース内で実行する SQL ステートメントに変数値を追加する方法がいくつかあります。

入力パラメーターを使用したデータベースクエリの保護

RDBMS から情報を取得するには ​select​ 操作を使用します。その操作の主な目標は、SQL クエリを提供し、DataWeave を使用してパラメーターを提供することです。

<flow name="selectParameterizedQuery">
  <db:select config-ref="dbConfig">
    <db:sql>SELECT * FROM PLANET WHERE name = :name</db:sql>
    <db:input-parameters>
      #[{'name' : payload}]
    </db:input-parameters>
  </db:select>
</flow>

この例では、入力パラメーターをキー-値ペアで提供します。このペアは、DataWeave スクリプトを埋め込むことで作成します。このキーをコロン文字 (​:​) と組み合わせて、名前によりパラメーター値を参照します。クエリでパラメーターを使用するには、この方法をお勧めします。

入力パラメーターを使用して ​SELECT​ ステートメントの ​WHERE​ 句を設定する利点は、クエリが SQL インジェクション攻撃の影響を受けなくなり、他の方法では不可能な最適化を実行でき、アプリケーションの全体的なパフォーマンスが向上することです。

バージョン 1.4.0 以降 (コロンのエスケープ):​ SQL クエリでコロン文字 (​:​) を使用する必要がある場合、コロン文字の前にバックスラッシュを置くことでコロン文字をエスケープできます。これは、PostgreSQL 種別のキャストを使用する場合に役立ちます。この場合、キャスト先の種別の前に 2 つのコロンが必要です。例:

<db:sql>SELECT price\:\:float8 FROM PRODUCT</db:sql>

バージョン 1.8.0 以降 (PostgreSQL および Snowflake の SQL キャスト)​:Database Connector は、各コロンをエスケープする必要なく、ダブルコロン (::) 表現を使用して SQL キャスト PostgreSQL および Snowflake 構文を受け入れるようになりました (この機能はコロンのエスケープの動作に影響しません)。次に例を示します。

<db:sql>SELECT MAX(modified_date)::DATE FROM sales</db:sql>

セキュリティ上の理由により、​<db:sql>SELECT * FROM PLANET WHERE name = #[payload] </db:sql>​ は直接記述しないでください。

操作の入力と出力には DataSense を使用できます。コネクタはクエリを分析し、SQL ステートメントの射影セクションを分析することで、クエリの出力構造を自動的に計算します。同時に、​WHERE​ 句の条件をテーブル構造と比較して、DataSense 入力も生成します。これは、入力パラメーターを生成する DataWeave スクリプトをビルドするのに役立ちます。

動的クエリ

場合によっては、​WHERE​ 句をパラメーター化するだけでなく、クエリ自体の一部をパラメーター化しなければならないことがあります。次のユースケースの例は、条件に応じてオンラインテーブルか履歴テーブルにアクセスする必要があるクエリ、またはプロジェクトテーブル列を変更する必要がある複雑なクエリです。

次の例では、テーブルが変数に依存することを記述する文字列 ​$(vars.table)​ をビルドしてクエリを生成するための完全な式を確認できます。重要なことは、一部のクエリテキストは動的 (​"SELECT * FROM $(vars.table)​) ですが、​WHERE​ 句では、入力パラメーターを使用して ​WHERE​ 条件を定義するベストプラクティスが引き続き使用されていることです (この例では ​WHERE name = :name​)。

<set-variable variableName="table" value="PLANET"/>
<db:select config-ref="dbConfig">
    <db:sql>#["SELECT * FROM $(vars.table) WHERE name = :name"]</db:sql>
    <db:input-parameters>
        #[{'name' : payload}]
    </db:input-parameters>
</db:select>

上記の例では動的クエリが必要であり、入力パラメーターのようには処理できません。入力パラメーターは、​WHERE​ 句のパラメーターにのみ適用できます。クエリの別の部分を変更するには、DataWeave の補間演算子を使用する必要があります。

Mule 3 では、選択の概念がパラメーター化クエリと動的クエリに分割されており、この両方を同時に使用することができませんでした。動的クエリを使用するか、パラメーターの使用から利点を得るか (SQL インジェクションの保護、PreparedStatement の最適化など) のどちらかを選択する必要がありました。また、それぞれ構文が異なるため、同じことを行うのに 2 つのやり方を学ぶ必要がありました。ただし、Mule 4 の Database Connector があれば、クエリ内で式を使用してこの両方の方法を同時に使用できるようになりました。

大量の結果のストリーミング

インテグレーションのユースケースなど、多くのレコードを返すクエリでストリーミングを使用します。Mule 4 では、ストリーミングは透過的であり、常に有効になっています。

たとえば、10K 行を返すクエリを送信した場合、それらすべての行を一度にフェッチしようとすると、ネットワークから大量の取り込みを行うため、パフォーマンスが低下し、すべての情報を RAM に読み込む必要があるため、メモリ不足になるリスクがあります。

ストリーミングでは、コネクタは一度にクエリの一部のみをフェッチおよび処理するため、ネットワークとメモリの負荷が軽減されます。 これは、コネクタが 10K 行を一度にフェッチしないことを意味します。代わりに、コネクタは小さなチャンクをフェッチし、そのチャンクが消費されたら残りをフェッチします。

新しい反復可能なストリームメカニズムを使用することもできます。これにより、DataWeave や他のコンポーネントで同じストリームを何度も処理できます。また、並列処理も可能です。反復可能なストリームについての詳細は、Mule 4.0 でのストリーミングを参照してください。

結果の制限

Mule を使用すると、コネクタでストリーミングを適切に処理できます。ただし、これは、データの大きなチャンクをデータベースから Mule に移動することをお勧めするものではありません。ストリーミングを使用しても、通常の SQL クエリで、各行に大量の情報を含む多くの行が返される可能性はあります。

select​ 操作では、これに役立つパラメーター (​fetchSize​ および ​maxRows​) が提供されます。

<db:select fetchSize="200" maxRows="1000" config-ref="dbConfig">
  <db:sql>select * from some_table</db:sql>
</db:select>

この構文は、フェッチできる合計行数は 1000 (​maxRows​ 値) 以下、一度にフェッチできる行数は 200 (​fetchSize​ 値) 以下であることをコネクタに指示します。これにより、ネットワークとメモリの負荷が大幅に軽減されます。​fetchSize​ 値は JDBC ドライバープロバイダーごとに異なって適用され、多くの場合、デフォルトで ​10​ に設定されます。

この組み合わせにより、取得される情報の総量が制限され (​maxRows​ 値)、ネットワーク経由でデータベースから小さいチャンクのデータが返されることが保証されます (​fetchSize​ 値)。

Query Timeout (クエリタイムアウト)

データベースクエリの実行に長い時間がかかる場合があります。多くの場合、次の要因によりクエリの実行が遅延します。

  • 非効率なクエリ (多くの行を反復処理する不適切なインデックスを持つクエリなど)

  • 混雑している RDBMS またはネットワーク

  • ロック競合

一般に、クエリにタイムアウトを設定することをお勧めします。タイムアウトを管理するには、​queryTimeout​ と ​queryTimeoutUnit​ を設定します。次の例は、Select 操作のタイムアウトの設定方法を示していますが、タイムアウトの設定はすべての操作でサポートされます。

<db:select queryTimeout="0" queryTimeoutUnit="SECONDS" config-ref="dbConfig">
   <db:sql>select * from some_table</db:sql>
</db:select>

データの挿入、更新、削除

Database Connector では、​insert​、​update​、および ​delete​ 操作がサポートされています。 select 操作と同様に、これらの操作では、埋め込みの DataWeave 変換を使用して、動的クエリとパラメーター化がサポートされます。また、​fetchSize​、​maxRows​、​timeout​ パラメーターもサポートされます。入力パラメーター化、動的クエリ、およびパラメーターの使用方法の例が提供されますが、詳細は、​SELECT​ 操作のドキュメントを参照してください。

Insert

electronic​ という名前のテーブルが含まれている ​Products​ という名前のデータベーススキーマがあるとします。​electronic​ テーブルには、​id​、​name​、​description​、​price​、​discount​ という列が含まれます。

次の SQL ステートメントでは、このテーブルを作成します。

CREATE TABLE electronic(
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    description VARCHAR(255),
    price SMALLINT,
    discount TINYINT
)

テーブルがすでに作成されていて、​dbConfig​ という名前の接続設定がある場合、次の操作で ​electronic​ テーブルに新しいレコードが挿入されます。

<db:insert config-ref="dbConfig">
  <db:sql>
    INSERT INTO electronic(name, description, price, discount)
    VALUES ('Coffee Machine', 'Model: XYZ99. Uses small size capsules.', 120, 5)
  </db:sql>
</db:insert>

id​ パラメーターは、データベースによって自動的に生成される自動増分キーであるため、クエリに渡されません。

入力パラメーターの利点を得るには、次のように同等のクエリを構築します。

<db:insert config-ref="dbConfig">
    <db:sql>
        INSERT INTO electronic(name, description, price, discount)
        VALUES (:name, :description, :price, :discount)
    </db:sql>
    <db:input-parameters>#[{
        name: 'Coffee Machine',
        description: 'Model:XYZ99. Uses small size capsules.',
        price: 120,
        discount: 5}]
    </db:input-parameters>
</db:insert>

insert 操作は、2 つの項目 (クエリの影響を受けた行数を示す整数 ​affectedRows​ と、自動生成されたキーが含まれるマップ ​generatedKeys​) が含まれる ​Statement Result​ オブジェクトを出力します。この例では、出力は次のようになります。

{
  "affectedRows": 1,
  "generatedKeys": {

  }
}

行は正常にテーブルに追加されていますが、マップ ​generatedKeys​ は空です。 マップが空になるのは、オーバーヘッドを回避するためにこの情報がデフォルトで無効になっているためです。 情報をアクティブ化してキーを生成するには、​autoGenerateKeys​ パラメーターを追加して ​true​ に設定します。

<db:insert config-ref="dbConfig" autoGenerateKeys="true">
   <db:sql>
       INSERT INTO electronic(name, description, price, discount)
       VALUES (:name, :description, :price, :discount)
   </db:sql>
   <db:input-parameters>#[{
       name: 'Coffee Machine',
       description: 'Model:XYZ99. Uses small size capsules.',
       price: 120,
       discount: 5}]
   </db:input-parameters>
</db:insert>

ステートメントで影響を受けた行ごとに複数のキーが生成される場合、パラメーター ​autoGeneratedKeysColumnNames​ を目的の列名が含まれるリストに設定して、返される列を指定できます。たとえば、​id​ 列のみが返されるようにするには、パラメーターを 1 つの文字列要素が含まれる DataWeave リストに設定します。

<db:insert config-ref="dbConfig" autoGenerateKeys="true" autoGeneratedKeysColumnNames="#[['id']]">
    ...
</db:insert>

Update (更新)

「挿入の例」で定義したテーブルの場合、価格値が 100 を越えているすべての項目の割引を 10 % に設定するように ​electronic​ を更新する操作は次のようになります。

<db:update config-ref="dbConfig">
    <db:sql><![CDATA[#["UPDATE electronic SET discount = :discount WHERE price > :price"]]]></db:sql>
	<db:input-parameters>#[{
        discount: 10,
        price: 100
    }]</db:input-parameters>
</db:update>

<![CDATA[…​]]>​ ラッパーにより、クエリで ​>​ や ​"​ などの特殊文字を使用できます。 ラッパーがない場合、これらの文字の XML でエスケープされたバージョン (​&gt;​ や ​&quot;​ など) を使用する必要があります。

XML コードビューの代わりにコネクタの Anypoint Studio ビジュアルユーザーインターフェースを使用する場合、[​SQL Query Text​ (SQL クエリテキスト)] ボックスに特殊文字を直接入力できます。入力された文字は、Anypoint Studio によって自動的に XML ビューのエスケープされたバージョンに変更されます。

Delete (削除)

insert​ の例で定義されたテーブルの場合、次の演算子は ​id: 1​ のレコードをテーブルから削除します。

<db:delete config-ref="dbConfig">
    <db:sql>DELETE FROM electronic WHERE id = :id</db:sql>
    <db:input-parameters>#[{
        id: 1
    }]</db:input-parameters>
</db:delete>

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

input​、​output​、および ​input-output​ パラメーターを組み合わせたストアドプロシージャーを呼び出します。

次に例を示します。

<!-- Invoke a procedure with input parameters -->
<db:stored-procedure config-ref="dbConfig">
    <db:sql>{ call updatePlanetDescription('Venus', :description) }</db:sql>
    <db:input-parameters>
        #[{'description' : payload}]
    </db:input-parameters>
</db:stored-procedure>

<!-- Invoke a procedure with input-output parameters -->
<db:stored-procedure config-ref="dbConfig">
  <db:sql>{ call doubleMyInt(:myInt) }</db:sql>
  <db:in-out-parameters>
      <db:in-out-parameter key="myInt" value="3"/>
  </db:in-out-parameters>
</db:stored-procedure>

<!-- Invoke a procedure with both input AND output parameters -->
<db:stored-procedure config-ref="dbConfig">
    <db:sql>{ call multiplyInts(:int1, :int2, :result1, :int3, :result2) }</db:sql>
    <db:input-parameters>
        #[{
            'int1' : 3,
            'int2' : 4,
            'int3' : 5
        }]
    </db:input-parameters>
    <db:output-parameters>
        <db:output-parameter key="result1" type="INTEGER"/>
        <db:output-parameter key="result2" type="INTEGER"/>
        <db:output-parameter key="myInt" type="INTEGER"/>
    </db:output-parameters>
</db:stored-procedure>

多くの組み合わせが可能です。

実行後、​output​と ​input-output​ パラメーターの結果の値は操作の結果内で利用できます。DataSense を活用すると、この値を容易に取得できます。

Database Connector バージョン 1.4.0 以降では、ストアドプロシージャーの名前と最初の括弧の間に空白がないことを確認してください。

Database Connector は、パラメーターが位置的に一致する ​{ call procedureName(:param1, :param2, …​, :paramN) }​ 形式である、つまり、​:paramN​ がストアドプロシージャー宣言の ​Nth​ パラメーターと一致する、コール可能なステートメントの使用をサポートしています。

次のテーブルとストアドプロシージャーを使用して初期化した Oracle データベースを使用しているとします。

    CREATE TABLE SYSTEM.employees(
        employee_id INTEGER GENERATED BY DEFAULT AS IDENTITY,
        employee_name VARCHAR2(100),
        employee_age INTEGER,
        employee_birthday TIMESTAMP,
        PRIMARY KEY(employee_id)
    );


    CREATE PROCEDURE createEmployee(e_name VARCHAR2, e_age NUMBER, e_birth_date DATE) AS
    BEGIN
        INSERT INTO SYSTEM.employees(employee_name, employee_age, employee_birthday) VALUES(e_name, e_age, e_birth_date);
    END;

コネクタはコール可能なステートメントでの名前付きパラメーターをサポートしていないため、名前 ({ call createEmployee(employee_age ⇒ :age, e_birth_date ⇒ :date, e_name ⇒ :name) }​) でパラメーターを一致させようとしても機能しません。パラメーターは適切な順序 ({ call createEmployee(e_name ⇒ :name, employee_age ⇒ :age, e_birth_date ⇒ :date) }​) で指定する必要があります。

ストアドプロシージャーのデータの使用

Database Connector は、エンジン固有の組み込み関数の使用をサポートしていません。たとえば、Oracle データベースでプロシージャーをコールする前に日付を特定の形式に変更する場合、{ call createEmployee(e_name ⇒ :name, employee_age ⇒ :age, e_birth_date ⇒ TO_DATE(:date, 'YYYY-MM-DD HH:mm:ss')) }.​ のアプローチは機能しません。
コール可能なステートメントを呼び出す前に、すべてのデータ変換で DataWeave を使用します。たとえば、前の例を使用して、次の変換を実行します。

<db:stored-procedure doc:name="Create Employee" config-ref="Database_Config">
    <db:sql>{ call createEmployee(:name, :age, :date) }</db:sql>
		<db:input-parameters>
		 	<![CDATA[#[%dw 2.0
				output application/json
				fun format(d: DateTime) = d as String { format: "yyyy-MM-dd HH:mm:ss" }
				---
				{ 'date': format(|2019-10-31T13:00:00.000Z|), 'name': 'rick', 'age': 60 }
			]]]>
		</db:input-parameters>
	</db:stored-procedure>

DDL ステートメントの実行

データ定義言語 (DDL) ステートメントは、データへの直接アクセスやデータの変更を行わない特別な種別の SQL ステートメントです。代わりに、データ構造やストアドプロシージャーなどの作成、変更、破棄を行います。DDL ステートメントを使用して、テーブルや他のデータ構造内のデータを作成または変更することもできます。

Create Table の例

Products​ という名前のデータベーススキーマがあり、​Products​ にアクセスするように設定されている ​dbConfig​ という名前の接続もあるとします。​Execute DDL​ という名前の次の操作は、​id​、​name​、​description​、​price​、​discount​ という名前の列がある ​electronic​ という名前の新しいテーブルを作成します。

<db:execute-ddl config-ref="dbConfig">
    <db:sql>
        CREATE TABLE electronic(
            id INT AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(100),
            description VARCHAR(255),
            price SMALLINT,
            discount TINYINT
        )
    </db:sql>
</db:execute-ddl>

Execute DDL​ 操作は、テーブルを作成し、エラーがなければ ​0​ を返します。

一括操作の実行

insert​、​update​、​delete​ 操作は、各入力パラメーターが 1 つの値のみを取る場合に使用できます。または、一括操作では、一連のパラメーター値を使用して 1 つのクエリを実行できます。

一括操作を実行すれば、不要なステップを回避して次の利点を得ることができます。

  • クエリは 1 回のみ解析される。

  • 実行されるステートメントは 1 つのみのため、必要なデータベース接続は 1 つのみである。

  • ネットワークオーバーヘッドが最小限に抑えられる。

  • RDBMS は一括操作をアトミックに実行できる。

このユースケースでは、コネクタは ​<db:bulk-insert>​、​<db:bulk-update>​、​<db:bulk-delete>​ の 3 つの操作を提供します。

これらの操作は、対応する単一操作と似ていますが、入力パラメーターをキー - 値のペアで受け取るのではなく、キー - 値のペアのリストとして受け取ることを想定しています。

次に例を示します。

<db:bulk-insert config-ref="dbConfig" >
  <db:bulk-input-parameters>
    #[[{'id': 2, 'name': 'George', 'lastName': 'Costanza'}, {'id': 3, 'name': 'Cosmo', 'lastName': 'Kramer'}]]
  </db:bulk-input-parameters>
  <db:sql>
    insert into customers (id, name, lastName) values (:id, :name, :lastName)
  </db:sql>
</db:bulk-insert>

一括操作を使用しない場合、​delete​ 操作の実行時に 1 つの条件 ​(POSITION = X)​ のみが提供されると、複数の行が条件に一致して削除される可能性があります。 同じ概念が更新にも適用されます。​UPDATE PRODUCTS set PRICE = PRICE * 0.9 where PRICE > :price​ を使用するときに、複数の商品に 10% 割引を適用したい場合でも、​price​ 入力パラメーターは 1 つの値のみを受け入れます。

価格の異なる商品に異なる割引率を適用するには、多くの操作を実行します。

次の例は、構造 ​{ price : number, discountRate: number}​ のオブジェクトのリストであるペイロードです。

<foreach>
  <db:update config-ref="dbConfig">
    <db:input-parameters>
     #[
      {
        'discountRate' : payload.discountRate,
        'price' : payload.price,
      }
    ]
    </db:input-parameters>
    <db:sql>
      UPDATE PRODUCTS set PRICE = PRICE * :discountRate where PRICE > :price
    </db:sql>
  </db:update>
</foreach>

前の操作ではタスクを遂行できますが、非効率的です。リストの要素ごとに、操作の各要素で 1 つのクエリを実行する必要があります。

  • クエリが解析される。

  • パラメーターが解決される。

  • データベースへの接続が取得される (プールから接続を取得するか、新しい接続を確立する)。

  • すべてのネットワークオーバーヘッドが支払われる。

  • RBMS でクエリを処理し、変更を適用する。

  • 接続が解放される。

いずれかの操作の実行中にエラーが発生した場合 (たとえば、100 行の一括挿入のうち 1 行の挿入に失敗した場合)、1 つの例外がスローされます。

一括操作の一部のステートメントは正常に実行できても、他のステートメントはエラーになる可能性があります。この場合、ドライバーが次のいずれかを実行します。

  1. 実行をすぐに停止し、残りのすべての操作を無視する

  2. 残りのステートメントの実行を続行する。

どちらの場合も、エラーが発生するたびにアプリケーションログを調べて、失敗の原因を確認できます。この場合、問題の原因を説明する 1 つの例外がスローされます。

Database Connector データ型リファレンス

次の例には、データベース入力パラメーターと、特定の接続プロバイダーに接続している場合に使用できるカスタムデータ型の定義方法に関する情報が含まれています。

パラメーターのデータ型の強制

まれに、基礎となる JDBC ドライバーで入力パラメーターを特定のデータ型に強制的に割り当てることが必要になる場合があります。たとえば、JDBC ドライバーで入力のデータ型を特定できない場合や、パラメーターがカスタムデータ型の場合、各入力パラメーターのデータ型を指定して、強制を適用しなければならないことがあります。

<db:bulk-insert queryTimeout="0" queryTimeoutUnit="SECONDS">
     <db:sql>INSERT INTO PLANET(POSITION, NAME) VALUES (:position, :name)</db:sql>
     <db:parameter-types>
         <db:parameter-type key="name" type="VARCHAR" />
         <db:parameter-type key="position" type="INTEGER" />
     </db:parameter-types>
 </db:bulk-insert>

カスタムデータ型の定義

接続プロバイダー (Derby、Oracle など) ごとに専用パラメーターと共通パラメーターがあります。接続プロバイダー要素の子要素で、特定のプロバイダーに接続している場合に使用できるカスタムデータ型を定義します。次に例を示します。

<db:config name="dbConfig">
   <db:derby-connection url="jdbc:derby:muleEmbeddedDB;create=true">
       <db:column-types>
           <!-- Derby uses JAVA_OBJECT for UDT-->
           <db:column-type typeName="CONTACT_DETAILS" id="2000"/>
       </db:column-types>
   </db:derby-connection>
</db:config>

データベースのトランザクション

データベース操作をトランザクションのコンテキストで実行できます。各操作に ​transactionalAction​ 値があります。これは、アクティブなトランザクションがある場合に、トランザクションに関して、操作で実行できる結合アクションの種別を特定します。たとえば、​select​ 操作には次の可能なアクションがあります。

  • ALWAYS_JOIN
    メッセージの受信時にトランザクションが進行中であると想定します。トランザクションがない場合、エラーが発生します。

  • JOIN_IF_POSSIBLE
    現在のトランザクションが使用可能な場合、そのトランザクションを結合します。それ以外の場合、トランザクションは実行されません。

  • NOT_SUPPORTED
    存在するトランザクションの外部で実行します。

操作のグループ化

場合によっては、複数のクエリを同じトランザクションのコンテキストでアトミックに実行する必要があります。たとえば、銀行口座振替中は 1 つの口座から金額を引き、別の口座に加える必要がありますが、この 2 つの操作のいずれかが失敗した場合、両方の操作をロールバックする必要があります。

<db:update config-ref=”db”>
 <db:sql>UPDATE ACCOUNT set BALANCE = BALANCE - :money where ID = :source</db:sql>
 <db:input-parameters>#[{‘money’ : payload.money, ‘source’: payload.source}]</db:input-parameters>
</db:update>

<db:update config-ref=”db”>
 <db:sql>UPDATE ACCOUNT set BALANCE = BALANCE + :money where ID = :target</db:sql>
 <db:input-parameters>#[{‘money’ : payload.money, ‘target’’: payload.target}]</db:input-parameters>
</db:update>

これらのクエリを、すでに存在するトランザクションのコンテキストで実行した場合、クエリは同じトランザクションに属します。アクティブなトランザクションがない場合は、​<try>​ スコープを使用してトランザクションを開始できます。

<try transactionalAction="ALWAYS_BEGIN">
 <db:update config-ref="db">
   <db:sql>UPDATE ACCOUNT set BALANCE = BALANCE - :money where ID = :source</db:sql>
   <db:input-parameters>#[{'money' : payload.money, 'source': payload.source}]</db:input-parameters>
 </db:update>

 <db:update config-ref="db">
   <db:sql>UPDATE ACCOUNT set BALANCE = BALANCE + :money where ID = :target</db:sql>
   <db:input-parameters>#[{'money' : payload.money, 'target'': payload.target}]</db:input-parameters>
 </db:update>
</try>

スクリプトの実行リファレンス

この操作ではランダムな長さのスクリプトを 1 つのステートメントとして実行します。スクリプト実行は、次のいくつかの点で他の操作と異なります。

  • スクリプトに複数のステートメントを含めることができる。

  • さまざまな種別のステートメントを使用できる。

  • 入力または出力パラメーターを受け入れることができない。

execute-script​ 操作では、SQL 射影を伴わない任意のスクリプトを実行します。次の方法で ​<db:execute-script>​ を使用できます。

  • 操作に ​execute-script​ を埋め込む。

  • ファイルから ​execute-script​ を参照する。

この両方のスクリプトの実行方法を同時に使用することはできません。

スクリプトを実行すると、整数の配列 (実行したステートメントごとに 1 つの要素) が返されます。各数値は、ステートメントの影響を受けたオブジェクトの数を表します。

操作への埋め込み

<db:execute-script config-ref="dbConfig">
   <db:sql>
       update PLANET set NAME='Mercury' where POSITION=0;
       update PLANET set NAME='Mercury' where POSITION=4
   </db:sql>
</db:execute-script>

ファイルからの参照

<flow name="executeScriptFromFile">
   <db:execute-script config-ref="dbConfig" file="integration/executescript/bulk-script.sql" />
</flow>

スクリプト実行操作では、スキーマとテーブルの作成、データの挿入、データの循環が頻繁に実行されます。データの循環は夜間ジョブで実行されます。このジョブでは、データを履歴テーブルに移動およびアーカイブし、オンラインテーブルをパージします。

スクリプト実行操作と一括操作では用途が異なります。 たとえば、データベースに多数の行を挿入するスクリプトをビルドできますが、スクリプトに動的パラメーターを都合よく提供することはできません。また、スクリプトで SQL インジェクション攻撃を防ぐ必要があります。

スクリプトで SELECT ステートメントを実行すると、データは返されず、データ入力の問題が生じます。