入站通道介面卡
入站通道介面卡的主要功能是執行 SQL SELECT
查詢並將結果集轉換為訊息。訊息負載是整個結果集(表示為一個 List
),列表項的型別取決於行對映策略。預設策略是一個通用對映器,它為查詢結果中的每一行返回一個 Map
。您可以選擇透過新增對 RowMapper
例項的引用來更改此行為(有關行對映的詳細資訊,請參閱Spring JDBC 文件)。
如果您希望將 SELECT 查詢結果中的行轉換為單獨的訊息,可以使用下游的拆分器(splitter)。 |
入站介面卡還需要對 JdbcTemplate
例項或 DataSource
的引用。
除了用於生成訊息的 SELECT
語句外,介面卡還有一個 UPDATE
語句,用於將記錄標記為已處理,以便它們不會出現在下一次輪詢中。更新操作可以透過原始 SELECT 查詢返回的 ID 列表進行引數化。預設情況下,這是透過命名約定完成的(輸入結果集中名為 id
的列會被轉換為更新操作的引數 Map 中名為 id
的列表)。以下示例定義了一個帶有更新查詢和 DataSource
引用的入站通道介面卡。
<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
來覆蓋預設行為(介面卡有一個 sql-parameter-source-factory
屬性)。Spring Integration 提供了 ExpressionEvaluatingSqlParameterSourceFactory
,它建立一個基於 SpEL 的引數源,並將查詢結果作為 #root
物件。(如果 update-per-row
為 true,則根物件是單行)。如果同一個引數名稱在更新查詢中多次出現,它只會被求值一次,並且其結果會被快取。
您還可以為 select 查詢使用引數源。在這種情況下,由於沒有要對其進行求值的“結果”物件,因此每次使用單個引數源(而不是使用引數源工廠)。從 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 工廠方法。否則,引數源會快取求值結果。另請注意,由於快取被停用,如果同一個引數名稱在 select 查詢中多次出現,則每次出現時都會重新求值。 |
輪詢與事務
入站介面卡接受常規的 Spring Integration 輪詢器作為子元素。因此,可以控制輪詢的頻率(以及其他用途)。對於 JDBC 用法,輪詢器的一個重要特性是可以在事務中包裝輪詢操作,如下例所示
<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>
如果您沒有顯式指定輪詢器,則使用預設值。與 Spring Integration 通常的做法一樣,預設輪詢器可以定義為頂級 Bean)。 |
在前面的示例中,資料庫每 1000 毫秒(即每秒一次)輪詢一次,並且更新和 SELECT 查詢都在同一事務中執行。此處未顯示事務管理器配置。但是,只要事務管理器知道資料來源,輪詢就是事務性的。一個常見的用例是下游通道是直接通道(預設),這樣端點在同一執行緒中呼叫,因此也在同一事務中。這樣,如果其中任何一個失敗,事務將回滾,輸入資料將恢復到其原始狀態。
max-rows
與 max-messages-per-poll
JDBC 入站通道介面卡定義了一個名為 max-rows
的屬性。當您指定介面卡的輪詢器時,您還可以定義一個名為 max-messages-per-poll
的屬性。雖然這兩個屬性看起來相似,但它們的含義卻完全不同。
max-messages-per-poll
指定每個輪詢間隔內查詢執行的次數,而 max-rows
指定每次執行返回的行數。
在正常情況下,您可能不希望在使用 JDBC 入站通道介面卡時設定輪詢器的 max-messages-per-poll
屬性。其預設值為 1
,這意味著 JDBC 入站通道介面卡的 receive()
方法在每個輪詢間隔內精確執行一次。
將 max-messages-per-poll
屬性設定為更大的值意味著查詢會連續執行多次。有關 max-messages-per-poll
屬性的更多資訊,請參閱配置入站通道介面卡。
相比之下,max-rows
屬性(如果大於 0
)指定了從 receive()
方法建立的查詢結果集中使用的最大行數。如果屬性設定為 0
,則所有行都包含在結果訊息中。此屬性預設為 0
。
建議透過特定供應商的查詢選項來限制結果集,例如 MySQL 的 LIMIT 或 SQL Server 的 TOP 或 Oracle 的 ROWNUM 。有關詳細資訊,請參閱特定供應商的文件。 |