此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.4.3! |
存储过程
在某些情况下,普通的 JDBC 支持是不够的。 也许您处理的是旧式关系数据库架构,或者您有复杂的数据处理需求,但最终您必须使用存储过程或存储函数。 从 Spring Integration 2.1 开始,我们提供了三个组件来执行存储过程或存储函数:
-
存储过程入站通道适配器
-
存储过程出站通道适配器
-
存储过程出站网关
支持的数据库
为了启用对存储过程和存储函数的调用,存储过程组件使用org.springframework.jdbc.core.simple.SimpleJdbcCall
类。
因此,完全支持以下数据库执行存储过程:
-
阿帕奇德比
-
DB2
-
MySQL (MySQL的
-
Microsoft SQL 服务器
-
神谕
-
PostgreSQL 数据库
-
Sybase
如果您想改为执行存储函数,则完全支持以下数据库:
-
MySQL (MySQL的
-
Microsoft SQL 服务器
-
神谕
-
PostgreSQL 数据库
即使您的特定数据库可能没有得到完全支持,只要您的 RDBMS 支持存储过程或存储函数,您很可能可以非常成功地使用存储过程 Spring Integration 组件。 事实上,一些提供的集成测试使用 H2 数据库。 尽管如此,全面测试这些使用场景非常重要。 |
常见配置属性
所有存储过程组件共享某些配置参数:
-
auto-startup
:生命周期属性,指示是否应在应用程序上下文启动期间启动此组件。 它默认为true
. 自选。 -
data-source
:对javax.sql.DataSource
,用于访问数据库。 必填。 -
id
:标识底层 Spring Bean 定义,它是EventDrivenConsumer
或PollingConsumer
,具体取决于出站通道适配器的channel
属性引用SubscribableChannel
或PollableChannel
. 自选。 -
ignore-column-meta-data
:对于完全支持的数据库,底层SimpleJdbcCall
class 可以从 JDBC 元数据中自动检索存储过程或存储函数的参数信息。但是,如果数据库不支持元数据查找,或者您需要提供自定义参数定义,则可以将此标志设置为
true
. 它默认为false
. 自选。 -
is-function
:如果true
时,将调用 SQL 函数。 在这种情况下,stored-procedure-name
或stored-procedure-name-expression
attributes 定义被调用函数的名称。 它默认为false
. 自选。 -
stored-procedure-name
:此属性指定存储过程的名称。 如果is-function
属性设置为true
,则此属性指定函数名称。 此属性或stored-procedure-name-expression
必须指定。 -
stored-procedure-name-expression
:此属性使用 SpEL 表达式指定存储过程的名称。 通过使用 SPEL,您可以访问完整的消息(如果可用),包括其 Headers 和有效负载。 您可以使用此属性在运行时调用不同的存储过程。 例如,您可以提供要作为消息标头执行的存储过程名称。 表达式必须解析为String
.如果
is-function
属性设置为true
,则此属性指定存储函数。 此属性或stored-procedure-name
必须指定。 -
jdbc-call-operations-cache-size
:定义缓存的最大数量SimpleJdbcCallOperations
实例。 基本上,对于每个存储过程名称,一个新的SimpleJdbcCallOperations
实例,作为回报,该实例将被缓存。Spring Integration 2.2 添加了 stored-procedure-name-expression
属性和jdbc-call-operations-cache-size
属性。默认缓存大小为
10
. 值0
禁用缓存。 不允许使用负值。如果启用 JMX,则有关
jdbc-call-operations-cache
作为 MBean 公开。 有关更多信息,请参阅 MBean Exporter 。 -
sql-parameter-source-factory
:(不适用于存储过程入站通道适配器。 对SqlParameterSourceFactory
. 默认情况下,传入的Message
payload 用作存储过程输入参数的源,方法是使用BeanPropertySqlParameterSourceFactory
.对于基本用例,这可能就足够了。 对于更复杂的选项,请考虑传入一个或多个
ProcedureParameter
值。 请参阅定义参数源。 自选。 -
use-payload-as-parameter-source
:(不适用于存储过程入站通道适配器。 如果设置为true
,则Message
用作提供参数的源。 如果设置为false
,但是,整个Message
可用作参数的源。如果未传入过程参数,则此属性默认为
true
. 这意味着,通过使用默认的BeanPropertySqlParameterSourceFactory
中,有效负载的 Bean 属性将用作存储过程或存储函数的参数值的源。但是,如果传入了过程参数,则此属性(默认情况下)的计算结果为
false
.ProcedureParameter
允许提供 SpEL 表达式。 因此,访问整个Message
. 在底层StoredProcExecutor
. 自选。
常见配置子元素
存储过程组件共享一组通用的子元素,您可以使用这些子元素来定义参数并将其传递给存储过程或存储函数。 以下元素可用:
-
parameter
-
returning-resultset
-
sql-parameter-definition
-
poller
-
parameter
:提供存储过程参数的机制。 参数可以是静态的,也可以是使用 SPEL 表达式提供的。<int-jdbc:parameter name="" (1) type="" (2) value=""/> (3) <int-jdbc:parameter name="" expression=""/> (4)
1 要传递到 Stored Procedure 或 Stored Function 的参数的名称。 必填。 2 此属性指定值的类型。 如果未提供任何内容,则此属性默认为 java.lang.String
. 仅当value
属性。 自选。3 参数的值。 您必须提供此属性或 expression
属性。 自选。4 而不是 value
属性,您可以指定一个 SPEL 表达式来传递参数的值。 如果指定expression
这value
属性。 自选。 自选。 -
returning-resultset
:存储过程可能会返回多个结果集。 通过设置一个或多个returning-resultset
元素中,您可以指定RowMappers
以转换每个返回的ResultSet
转换为有意义的对象。 自选。<int-jdbc:returning-resultset name="" row-mapper="" />
-
sql-parameter-definition
:如果使用完全支持的数据库,则通常不必指定存储过程参数定义。 相反,这些参数可以自动从 JDBC 元数据派生。 但是,如果您使用的数据库不完全受支持,则必须使用sql-parameter-definition
元素。您还可以选择关闭对通过 JDBC 获取的参数元数据信息的任何处理,方法是使用
ignore-column-meta-data
属性。<int-jdbc:sql-parameter-definition name="" (1) direction="IN" (2) type="STRING" (3) scale="5" (4) type-name="FOO_STRUCT" (5) return-type="fooSqlReturnType"/> (6)
1 | 指定 SQL 参数的名称。 必填。 |
2 | 指定 SQL 参数定义的方向。
默认为IN .
有效值为:IN ,OUT 和INOUT .
如果您的过程返回结果集,请使用returning-resultset 元素。
自选。 |
3 | 用于此 SQL 参数定义的 SQL 类型。
转换为整数值,定义如下java.sql.Types .
或者,您也可以提供整数值。
如果未明确设置此属性,则默认为 'VARCHAR'。
自选。 |
4 | SQL 参数的比例。 仅用于数字和十进制参数。 自选。 |
5 | 这typeName 对于用户命名的类型,例如:STRUCT ,DISTINCT ,JAVA_OBJECT 和命名数组类型。
此属性与scale 属性。
自选。 |
6 | 对复杂类型的自定义值处理程序的引用。
的实现SqlReturnType .
此属性与scale 属性,仅适用于 OUT 和 INOUT 参数。
自选。
|
定义参数源
参数源控制检索 Spring 集成消息属性并将其映射到相关存储过程输入参数的技术。
存储过程组件遵循某些规则。
默认情况下,Message
payload 用作存储过程的输入参数的源。
在这种情况下,一个BeanPropertySqlParameterSourceFactory
被使用。
对于基本用例,这可能就足够了。
下一个示例说明了该默认行为。
要使用BeanPropertySqlParameterSourceFactory 要工作,您的 Bean 属性必须以小写形式定义。
这是因为在org.springframework.jdbc.core.metadata.CallMetaDataContext (Java 方法是matchInParameterValuesWithCallParameters() ),则检索到的存储过程参数声明将转换为小写。
因此,如果您有驼峰式 bean 属性(例如lastName ),则查找失败。
在这种情况下,请提供显式的ProcedureParameter . |
假设我们有一个有效负载,它由一个具有以下三个属性的简单 bean 组成:id
,name
和description
.
此外,我们有一个名为INSERT_COFFEE
接受三个 input 参数:id
,name
和description
.
我们还使用完全支持的数据库。
在这种情况下,存储过程出站适配器的以下配置就足够了:
<int-jdbc:stored-proc-outbound-channel-adapter data-source="dataSource"
channel="insertCoffeeProcedureRequestChannel"
stored-procedure-name="INSERT_COFFEE"/>
对于更复杂的选项,请考虑传入一个或多个ProcedureParameter
值。
如果您提供ProcedureParameter
值显式地显示,默认情况下,ExpressionEvaluatingSqlParameterSourceFactory
用于参数处理,以启用 SpEL 表达式的全部功能。
如果您需要对参数的检索方式进行更多控制,请考虑传入SqlParameterSourceFactory
通过使用sql-parameter-source-factory
属性。
存储过程入站通道适配器
下面的清单列出了对存储过程入站通道适配器很重要的属性:
<int-jdbc:stored-proc-inbound-channel-adapter
channel="" (1)
stored-procedure-name=""
data-source=""
auto-startup="true"
id=""
ignore-column-meta-data="false"
is-function="false"
skip-undeclared-results="" (2)
return-value-required="false" (3)
<int:poller/>
<int-jdbc:sql-parameter-definition name="" direction="IN"
type="STRING"
scale=""/>
<int-jdbc:parameter name="" type="" value=""/>
<int-jdbc:parameter name="" expression=""/>
<int-jdbc:returning-resultset name="" row-mapper="" />
</int-jdbc:stored-proc-inbound-channel-adapter>
1 | 轮询消息发送到的通道。
如果存储过程或函数未返回任何数据,则Message 为 null。
必填。 |
2 | 如果此属性设置为true ,则存储过程调用的所有结果都没有相应的SqlOutParameter 声明。
例如,存储过程可以返回更新计数值,即使存储过程仅声明一个 result 参数。
确切的行为取决于数据库实现。
该值在底层JdbcTemplate .
该值默认为true .
自选。 |
3 | 指示是否应包含此过程的返回值。 从 Spring Integration 3.0 开始。 自选。 |
存储过程出站通道适配器
下面的清单列出了对存储过程出站通道适配器很重要的属性:
<int-jdbc:stored-proc-outbound-channel-adapter channel="" (1)
stored-procedure-name=""
data-source=""
auto-startup="true"
id=""
ignore-column-meta-data="false"
order="" (2)
sql-parameter-source-factory=""
use-payload-as-parameter-source="">
<int:poller fixed-rate=""/>
<int-jdbc:sql-parameter-definition name=""/>
<int-jdbc:parameter name=""/>
</int-jdbc:stored-proc-outbound-channel-adapter>
1 | 此终端节点的接收消息通道。 必填。 |
2 | 指定此终端节点作为订阅者连接到通道时的调用顺序。
当该通道使用failover 调度策略。
当此终端节点本身是具有队列的通道的轮询使用者时,它不起作用。
自选。 |
存储过程出站网关
下面的清单列出了对存储过程出站通道适配器很重要的属性:
<int-jdbc:stored-proc-outbound-gateway request-channel="" (1)
stored-procedure-name=""
data-source=""
auto-startup="true"
id=""
ignore-column-meta-data="false"
is-function="false"
order=""
reply-channel="" (2)
reply-timeout="" (3)
return-value-required="false" (4)
skip-undeclared-results="" (5)
sql-parameter-source-factory=""
use-payload-as-parameter-source="">
<int-jdbc:sql-parameter-definition name="" direction="IN"
type=""
scale="10"/>
<int-jdbc:sql-parameter-definition name=""/>
<int-jdbc:parameter name="" type="" value=""/>
<int-jdbc:parameter name="" expression=""/>
<int-jdbc:returning-resultset name="" row-mapper="" />
1 | 此终端节点的接收消息通道。 必填。 |
2 | 收到数据库响应后应将回复发送到的消息通道。 自选。 |
3 | 允许您指定此网关在引发异常之前等待成功发送回复消息的时间。
请记住,当发送到DirectChannel ,则调用发生在发送方的线程中。
因此,send作的失败可能是由下游的其他组件引起的。
该值以毫秒为单位指定。
自选。 |
4 | 指示是否应包含此过程的返回值。 自选。 |
5 | 如果skip-undeclared-results 属性设置为true ,则存储过程调用的所有结果都没有相应的SqlOutParameter 声明。
例如,存储过程可能会返回更新计数值,即使存储过程只声明了一个 result 参数。
确切的行为取决于数据库。
该值在底层JdbcTemplate .
该值默认为true .
自选。 |
例子
本节包含两个调用 Apache Derby 存储过程的示例。
第一个过程调用一个存储过程,该存储过程返回一个ResultSet
.
通过使用RowMapper
,数据将转换为域对象,然后成为 Spring Integration 消息有效负载。
在第二个示例中,我们调用了一个存储过程,该过程使用输出参数来返回数据。
该项目包含此处引用的 Apache Derby 示例,以及有关如何运行它的说明。 Spring Integration Samples 项目还提供了一个使用 Oracle 存储过程的示例。 |
在第一个示例中,我们将名为FIND_ALL_COFFEE_BEVERAGES
,它不定义任何输入参数,但返回一个ResultSet
.
在 Apache Derby 中,存储过程是用 Java 实现的。 下面的清单显示了方法签名:
public static void findAllCoffeeBeverages(ResultSet[] coffeeBeverages)
throws SQLException {
...
}
下面的清单显示了相应的 SQL:
CREATE PROCEDURE FIND_ALL_COFFEE_BEVERAGES() \
PARAMETER STYLE JAVA LANGUAGE JAVA MODIFIES SQL DATA DYNAMIC RESULT SETS 1 \
EXTERNAL NAME 'o.s.i.jdbc.storedproc.derby.DerbyStoredProcedures.findAllCoffeeBeverages';
在 Spring Integration 中,您现在可以通过使用stored-proc-outbound-gateway
,如下例所示:
<int-jdbc:stored-proc-outbound-gateway id="outbound-gateway-storedproc-find-all"
data-source="dataSource"
request-channel="findAllProcedureRequestChannel"
expect-single-result="true"
stored-procedure-name="FIND_ALL_COFFEE_BEVERAGES">
<int-jdbc:returning-resultset name="coffeeBeverages"
row-mapper="org.springframework.integration.support.CoffeBeverageMapper"/>
</int-jdbc:stored-proc-outbound-gateway>
在第二个示例中,我们将名为FIND_COFFEE
,该参数具有一个 input 参数。
而不是返回ResultSet
,则它使用 output 参数。
以下示例显示了方法签名:
public static void findCoffee(int coffeeId, String[] coffeeDescription)
throws SQLException {
...
}
下面的清单显示了相应的 SQL:
CREATE PROCEDURE FIND_COFFEE(IN ID INTEGER, OUT COFFEE_DESCRIPTION VARCHAR(200)) \
PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME \
'org.springframework.integration.jdbc.storedproc.derby.DerbyStoredProcedures.findCoffee';
在 Spring 集成中,您现在可以通过使用stored-proc-outbound-gateway
,如下例所示:
<int-jdbc:stored-proc-outbound-gateway id="outbound-gateway-storedproc-find-coffee"
data-source="dataSource"
request-channel="findCoffeeProcedureRequestChannel"
skip-undeclared-results="true"
stored-procedure-name="FIND_COFFEE"
expect-single-result="true">
<int-jdbc:parameter name="ID" expression="payload" />
</int-jdbc:stored-proc-outbound-gateway>