入站通道介面卡
入站通道介面卡的主要功能是執行 SQL SELECT 查詢並將結果集轉換為訊息。訊息負載是整個結果集(表示為 List),列表中各項的型別取決於行對映策略。預設策略是通用對映器,它為查詢結果中的每一行返回一個 Map。您可以選擇透過新增對 RowMapper 例項的引用來更改此設定(有關行對映的更詳細資訊,請參閱 Spring JDBC 文件)。
如果您想將 SELECT 查詢結果中的行轉換為單獨的訊息,可以使用下游拆分器。 |
入站介面卡還需要引用 JdbcTemplate 例項或 DataSource。
除了生成訊息的 SELECT 語句外,介面卡還有一個 UPDATE 語句,用於將記錄標記為已處理,以便它們在下次輪詢時不再出現。更新可以由原始選擇中的 ID 列表引數化。預設情況下,這是透過命名約定完成的(輸入結果集中名為 id 的列在更新的引數對映中轉換為名為 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,則根物件為行)。如果同一個引數名稱在更新查詢中多次出現,則只評估一次並快取其結果。
您還可以為選擇查詢使用引數源。在這種情況下,由於沒有可供評估的“結果”物件,每次都使用單個引數源(而不是使用引數源工廠)。從版本 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 工廠方法。否則,引數源會快取評估結果。另請注意,由於快取已停用,如果選擇查詢中多次出現同一個引數名稱,則會為每次出現重新評估。 |
輪詢與事務
入站介面卡接受一個常規的 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 毫秒(即每秒一次)輪詢一次,並且更新和選擇查詢都在同一個事務中執行。未顯示事務管理器配置。然而,只要它知道資料來源,輪詢就是事務性的。一個常見的用例是下游通道是直接通道(預設),以便在同一個執行緒中呼叫端點,因此在同一個事務中。這樣,如果其中任何一個失敗,事務就會回滾,輸入資料就會恢復到原始狀態。
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。有關詳細資訊,請參閱特定供應商文件。 |