如需使用最新稳定版本,请使用 Spring Integration 7.0.4spring-doc.cadn.net.cn

入站通道适配器

入站通道适配器的主要功能是执行 SQL SELECT 查询,并将结果集转换为消息。 消息负载是整个结果集(表示为 List),列表中项的类型取决于行映射策略。 默认策略是一个通用映射器,它会为查询结果中的每一行返回一个 Map。 可选地,您可以通过添加对 RowMapper 实例的引用来更改此行为(有关行映射的更详细信息,请参阅 Spring JDBC 文档)。spring-doc.cadn.net.cn

如果您希望将 SELECT 查询结果中的行转换为单独的消息,可以使用下游拆分器。

入站适配器还需要对 JdbcTemplate 实例或 DataSource 的引用。spring-doc.cadn.net.cn

除了用于生成消息的SELECT语句外,适配器还有一个UPDATE语句,用于将记录标记为已处理,使其不会在下一次轮询中显示。 该更新可以通过原始 select 查询返回的 ID 列表进行参数化。 默认情况下,这是通过命名约定完成的(输入结果集中名为id的列被转换为更新参数映射中的名为id的列表)。 以下示例定义了一个具有更新查询和DataSource引用的入站通道适配器。spring-doc.cadn.net.cn

<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,则根对象是行)。 如果更新查询中多次出现相同的参数名称,则仅计算一次,并缓存其结果。spring-doc.cadn.net.cn

您也可以为 select 查询使用参数源。 在这种情况下,由于没有“result”对象可供评估,因此每次使用单个参数源(而不是使用参数源工厂)。 从版本 4.0 开始,您可以使用 Spring 创建基于 SpEL 的参数源,如下例所示:spring-doc.cadn.net.cn

<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)。spring-doc.cadn.net.cn

从版本 5.0 开始,您可以将 ExpressionEvaluatingSqlParameterSourceFactorysqlParameterTypes 一起使用,以指定特定参数的目标 SQL 类型。spring-doc.cadn.net.cn

以下示例提供了查询中使用的参数的 SQL 类型:spring-doc.cadn.net.cn

<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 使用,轮询器的一个重要特性是能够将轮询操作包装在事务中,如下例所示:spring-doc.cadn.net.cn

<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 毫秒(即每秒)轮询一次,且更新和查询操作均在同一个事务中执行。 事务管理器的配置未显示。 但只要其感知到数据源,轮询操作就是事务性的。 一种常见的使用场景是下游通道为直接通道(默认),以便端点在同一线程中被调用,从而处于同一事务中。 这样,如果其中任何一个失败,事务将回滚,输入数据也会恢复到原始状态。spring-doc.cadn.net.cn

max-rows对比max-messages-per-poll

JDBC 入站通道适配器定义了一个名为 max-rows 的属性。 当您指定适配器的轮询器时,还可以定义一个名为 max-messages-per-poll 的属性。 虽然这两个属性看起来相似,但它们的含义却大不相同。spring-doc.cadn.net.cn

max-messages-per-poll 指定每个轮询间隔内查询执行的次数,而 max-rows 指定每次执行返回的行数。spring-doc.cadn.net.cn

在正常情况下,当您使用 JDBC 入站通道适配器时,通常不希望将轮询器的 max-messages-per-poll 属性设置为该值。 其默认值为 1,这意味着对于每个轮询间隔,JDBC 入站通道适配器的 receive() 方法将恰好执行一次。spring-doc.cadn.net.cn

max-messages-per-poll 属性设置为更大的值意味着查询将连续执行该次数。 有关 max-messages-per-poll 属性的更多信息,请参阅 配置入站通道适配器spring-doc.cadn.net.cn

相比之下,max-rows属性如果大于0,则指定从由receive()方法创建的查询结果集中使用的最大行数。 如果该属性设置为0,则所有行都包含在结果消息中。 该属性的默认值为0spring-doc.cadn.net.cn

建议通过特定于数据库提供商的查询选项来限制结果集,例如 MySQL LIMIT、SQL Server TOP 或 Oracle 的 ROWNUM。 有关更多信息,请参阅相关提供商的文档。