送信チャネルアダプター

送信チャネルアダプターは受信の逆です。そのロールは、メッセージを処理し、それを使用して SQL クエリを実行することです。デフォルトでは、次の例に示すように、メッセージペイロードとヘッダーはクエリへの入力パラメーターとして使用できます。

<int-jdbc:outbound-channel-adapter
    query="insert into items (id, status, name) values (:headers[id], 0, :payload[something])"
    data-source="dataSource"
    channel="input"/>

前の例では、input というラベルの付いたチャネルに到着するメッセージには、キーが something のマップのペイロードがあるため、[] オペレーターはその値をマップから逆参照します。ヘッダーは、マップとしてもアクセスされます。

上記のクエリのパラメーターは、受信メッセージの Bean プロパティ式です(SpEL 式ではありません)。この動作は SqlParameterSource の一部であり、これは送信アダプターによって作成されるデフォルトのソースです。異なる動作を得るために、異なる SqlParameterSourceFactory を注入できます。

発信アダプターには、DataSource または JdbcTemplate への参照が必要です。SqlParameterSourceFactory を挿入して、各受信メッセージのクエリへのバインドを制御することもできます。

入力チャネルが直接チャネルの場合、送信アダプターはクエリを同じスレッドで実行するため、メッセージの送信者と同じトランザクション(存在する場合)を実行します。

SpEL 式を使用してパラメーターを渡す

ほとんどの JDBC チャネルアダプターの一般的な要件は、SQL クエリまたはストアドプロシージャまたは関数の一部としてパラメーターを渡すことです。前述のように、これらのパラメーターはデフォルトでは Bean プロパティ式であり、SpEL 式ではありません。ただし、SpEL 式をパラメーターとして渡す必要がある場合は、明示的に SqlParameterSourceFactory を注入する必要があります。

次の例では、ExpressionEvaluatingSqlParameterSourceFactory を使用してその要件を実現しています。

<jdbc:outbound-channel-adapter data-source="dataSource" channel="input"
    query="insert into MESSAGES (MESSAGE_ID,PAYLOAD,CREATED_DATE) values (:id, :payload, :createdDate)"
    sql-parameter-source-factory="spelSource"/>

<bean id="spelSource"
      class="o.s.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory">
    <property name="parameterExpressions">
        <map>
            <entry key="id"          value="headers['id'].toString()"/>
            <entry key="createdDate" value="new java.util.Date()"/>
            <entry key="payload"     value="payload"/>
        </map>
    </property>
</bean>

詳細については、パラメーターソースの定義を参照してください。

PreparedStatement コールバックの使用

場合によっては、SqlParameterSourceFactory の柔軟性と疎結合では、ターゲット PreparedStatement に必要なことを実行できないか、低レベルの JDBC 作業を行う必要があります。Spring JDBC モジュールは、実行環境(ConnectionCallback や PreparedStatementCreator など)を構成し、パラメーター値(SqlParameterSource など)を操作するための API を提供します。StatementCallback などの低レベル操作の API にもアクセスできます。

Spring Integration 4.2 以降、MessagePreparedStatementSetter では、requestMessage コンテキストで、PreparedStatement のパラメーターを手動で指定できます。このクラスは、標準の Spring JDBC API の PreparedStatementSetter とまったく同じロールを果たします。実際には、JdbcMessageHandler が JdbcTemplate で execute を呼び出すときに、インライン PreparedStatementSetter 実装から直接呼び出されます。

この関数インターフェースオプションは sqlParameterSourceFactory と相互に排他的であり、requestMessage から PreparedStatement のパラメーターを取り込むためのより強力な代替手段として使用できます。例: File データを DataBase BLOB 列にストリーミング方式で保存する必要がある場合に役立ちます。次の例は、その方法を示しています。

@Bean
@ServiceActivator(inputChannel = "storeFileChannel")
public MessageHandler jdbcMessageHandler(DataSource dataSource) {
    JdbcMessageHandler jdbcMessageHandler = new JdbcMessageHandler(dataSource,
            "INSERT INTO imagedb (image_name, content, description) VALUES (?, ?, ?)");
    jdbcMessageHandler.setPreparedStatementSetter((ps, m) -> {
        ps.setString(1, m.getHeaders().get(FileHeaders.FILENAME));
        try (FileInputStream inputStream = new FileInputStream((File) m.getPayload()); ) {
            ps.setBlob(2, inputStream);
        }
        catch (Exception e) {
            throw new MessageHandlingException(m, e);
        }
        ps.setClob(3, new StringReader(m.getHeaders().get("description", String.class)));
    });
    return jdbcMessageHandler;
}

XML 構成の観点から、prepared-statement-setter 属性は <int-jdbc:outbound-channel-adapter> コンポーネントで利用可能です。MessagePreparedStatementSetter Bean 参照を指定できます。

バッチ更新

バージョン 5.1 以降、リクエストメッセージのペイロードが Iterable インスタンスである場合、JdbcMessageHandler は JdbcOperations.batchUpdate() を実行します。Iterable の各要素は、そのような要素がまだ Message でない場合、リクエストメッセージからのヘッダーを使用して Message にラップされます。通常の SqlParameterSourceFactory ベースの構成の場合、これらのメッセージは、前述の JdbcOperations.batchUpdate() 関数で使用される引数の SqlParameterSource[] を構築するために使用されます。MessagePreparedStatementSetter 構成が適用されると、BatchPreparedStatementSetter バリアントを使用して各アイテムのメッセージが繰り返され、提供された MessagePreparedStatementSetter がそれらに対して呼び出されます。keysGenerated モードを選択した場合、一括更新はサポートされません。