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-rows
與 max-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 。有關更多資訊,請參閱特定供應商的文件。 |