Inbound Channel Adapter

Inbound Channel Adapter 的主要功能是執行 SQL SELECT 查詢,並將結果集轉換為訊息。訊息的 payload 是整個結果集 (以 List 表示),而列表中項目的類型取決於資料列對應策略。預設策略是通用 mapper,它為查詢結果中的每一列返回一個 Map。您可以選擇性地透過新增對 RowMapper 實例的參考來變更此設定 (有關資料列對應的更詳細資訊,請參閱 Spring JDBC 文件)。

如果您想將 SELECT 查詢結果中的資料列轉換為個別訊息,則可以使用下游的 splitter。

Inbound Adapter 也需要參考 JdbcTemplate 實例或 DataSource

除了用於產生訊息的 SELECT 語句外,Adapter 還具有 UPDATE 語句,用於將記錄標記為已處理,使其不會在下次輪詢中再次出現。更新可以透過原始 select 中的 ID 列表進行參數化。預設情況下,這是透過命名慣例完成的 (輸入結果集中名為 id 的欄位會轉換為更新參數映射中名為 id 的列表)。以下範例定義了一個具有更新查詢和 DataSource 參考的 inbound channel adapter。

<int-jdbc:inbound-channel-adapter query="select * from item where status=2"
    channel="target" data-source="dataSource"
    update="update item set status=10 where id in (:id)" />
更新查詢中的參數使用冒號 (:) 前綴指定參數名稱 (在前面的範例中,這是一個應用於輪詢結果集中每一列的表達式)。這是 Spring JDBC 中具名參數 JDBC 支援的標準功能,並結合了 Spring Integration 中採用的慣例 (投影到輪詢結果列表)。底層的 Spring JDBC 功能限制了可用的表達式 (例如,大多數句點以外的特殊字元是不允許的),但由於目標通常是可透過 bean 路徑定址的物件列表 (可能是一個列表),因此這並非過於嚴苛的限制。

若要變更參數產生策略,您可以將 SqlParameterSourceFactory 注入到 Adapter 中,以覆寫預設行為 (Adapter 具有 sql-parameter-source-factory 屬性)。Spring Integration 提供了 ExpressionEvaluatingSqlParameterSourceFactory,它會建立一個基於 SpEL 的參數來源,並將查詢結果作為 #root 物件。(如果 update-per-row 為 true,則根物件為資料列)。如果同一個參數名稱在更新查詢中多次出現,則只會評估一次,並且其結果會被快取。

您也可以將參數來源用於 select 查詢。在這種情況下,由於沒有要評估的「結果」物件,因此每次都會使用單一參數來源 (而不是使用參數來源 factory)。從 4.0 版開始,您可以使用 Spring 建立基於 SpEL 的參數來源,如下列範例所示

<int-jdbc:inbound-channel-adapter query="select * from item where status=:status"
	channel="target" data-source="dataSource"
	select-sql-parameter-source="parameterSource" />

<bean id="parameterSource" factory-bean="parameterSourceFactory"
			factory-method="createParameterSourceNoCache">
	<constructor-arg value="" />
</bean>

<bean id="parameterSourceFactory"
		class="o.s.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory">
	<property name="parameterExpressions">
		<map>
			<entry key="status" value="@statusBean.which()" />
		</map>
	</property>
</bean>

<bean id="statusBean" class="foo.StatusDetermination" />

每個參數表達式中的 value 可以是任何有效的 SpEL 表達式。用於表達式評估的 #root 物件是在 parameterSource bean 上定義的建構子引數。它對於所有評估都是靜態的 (在前面的範例中,是一個空的 String)。

從 5.0 版開始,您可以為 ExpressionEvaluatingSqlParameterSourceFactory 提供 sqlParameterTypes,以指定特定參數的目標 SQL 類型。

以下範例提供了查詢中使用的參數的 SQL 類型

<int-jdbc:inbound-channel-adapter query="select * from item where status=:status"
    channel="target" data-source="dataSource"
    select-sql-parameter-source="parameterSource" />

<bean id="parameterSource" factory-bean="parameterSourceFactory"
            factory-method="createParameterSourceNoCache">
    <constructor-arg value="" />
</bean>

<bean id="parameterSourceFactory"
        class="o.s.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory">
    <property name="sqlParameterTypes">
        <map>
            <entry key="status" value="#{ T(java.sql.Types).BINARY}" />
        </map>
    </property>
</bean>
使用 createParameterSourceNoCache factory 方法。否則,參數來源會快取評估結果。另請注意,由於停用了快取,如果同一個參數名稱在 select 查詢中多次出現,則每次出現都會重新評估。

輪詢和交易

Inbound Adapter 接受常規的 Spring Integration poller 作為子元素。因此,可以控制輪詢的頻率 (以及其他用途)。對於 JDBC 用途,poller 的一個重要功能是選擇將輪詢操作包裝在交易中,如下列範例所示

<int-jdbc:inbound-channel-adapter query="..."
        channel="target" data-source="dataSource" update="...">
    <int:poller fixed-rate="1000">
        <int:transactional/>
    </int:poller>
</int-jdbc:inbound-channel-adapter>
如果您未明確指定 poller,則會使用預設值。與 Spring Integration 的通常情況一樣,它可以定義為最上層的 bean)。

在前面的範例中,資料庫每 1000 毫秒 (或每秒一次) 輪詢一次,並且更新和 select 查詢都在同一個交易中執行。交易管理器組態未顯示。但是,只要它知道資料來源,輪詢就是交易性的。一個常見的用例是下游通道是直接通道 (預設值),以便端點在同一個執行緒中調用,因此也在同一個交易中。這樣,如果它們中的任何一個失敗,交易都會回滾,並且輸入資料會還原到其原始狀態。

max-rowsmax-messages-per-poll 的比較

JDBC inbound channel adapter 定義了一個名為 max-rows 的屬性。當您指定 Adapter 的 poller 時,您還可以定義一個名為 max-messages-per-poll 的屬性。雖然這兩個屬性看起來很相似,但它們的含義卻截然不同。

max-messages-per-poll 指定每個輪詢間隔執行查詢的次數,而 max-rows 指定每次執行返回的資料列數。

在正常情況下,當您使用 JDBC inbound channel adapter 時,您可能不希望設定 poller 的 max-messages-per-poll 屬性。其預設值為 1,這表示 JDBC inbound channel adapter 的 receive() 方法對於每個輪詢間隔只執行一次。

max-messages-per-poll 屬性設定為較大的值表示查詢會連續執行多次。有關 max-messages-per-poll 屬性的更多資訊,請參閱 設定 Inbound Channel Adapter

相反地,max-rows 屬性 (如果大於 0) 指定要從 receive() 方法建立的查詢結果集中使用的最大資料列數。如果該屬性設定為 0,則所有資料列都包含在產生的訊息中。該屬性預設為 0

建議透過供應商特定的查詢選項來使用結果集限制,例如 MySQL LIMIT 或 SQL Server TOP 或 Oracle 的 ROWNUM。有關更多資訊,請參閱特定供應商的文件。