出站通道介面卡

出站通道介面卡與入站通道介面卡相反:它的作用是處理訊息並使用它來執行 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 以獲得不同的行為。

出站介面卡需要引用 DataSourceJdbcTemplate。您還可以注入 SqlParameterSourceFactory 來控制每個傳入訊息與查詢的繫結。為了更流暢地使用 SqlParameterSourceFactory(特別是預設的 BeanPropertySqlParameterSourceFactory 及其 MapSqlParameterSource),從版本 6.5 開始,JdbcMessageHandler 公開了一個 usePayloadAsParameterSource 標誌,用於指示是否應將整個訊息作為引數源輸入傳遞。

如果輸入通道是直接通道,出站介面卡會在與訊息傳送者相同的執行緒中執行其查詢,因此也在相同的事務中(如果存在)。

使用 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 模組提供了配置執行環境(如 ConnectionCallbackPreparedStatementCreator)和操作引數值(如 SqlParameterSource)的 API。它甚至可以訪問低階操作的 API,如 StatementCallback

從 Spring Integration 4.2 開始,MessagePreparedStatementSetter 允許在 requestMessage 上下文中手動指定 PreparedStatement 上的引數。此類的作用與標準 Spring JDBC API 中的 PreparedStatementSetter 完全相同。實際上,當 JdbcMessageHandlerJdbcTemplate 上呼叫 execute 時,它直接從內聯 PreparedStatementSetter 實現中呼叫。

此函式式介面選項與 sqlParameterSourceFactory 互斥,並且可以作為一種更強大的替代方案,用於從 requestMessage 填充 PreparedStatement 的引數。例如,當我們需要以流式方式將 File 資料儲存到資料庫 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 的配置情況下,這些訊息用於構建一個 SqlParameterSource[],作為上述 JdbcOperations.batchUpdate() 函式的引數。當應用 MessagePreparedStatementSetter 配置時,將使用 BatchPreparedStatementSetter 變體來迭代這些訊息中的每個項,並針對它們呼叫提供的 MessagePreparedStatementSetter。當選擇 keysGenerated 模式時,不支援批次更新。

© . This site is unofficial and not affiliated with VMware.