我如何配置此 JdbcMessageHandler 以从消息而不是静态 bean 中提取参数?
How do I configure this JdbcMessageHandler to pull parameters from the message instead of static beans?
症状:
调用时,此子流的 cleanupMessageHandler
组件(JdbcMessageHandler)不会从消息中提取参数,而是尝试从静态 bean 中提取参数。
异常信息:
org.springframework.dao.InvalidDataAccessApiUsageException:没有为 SQL 参数提供值 'ALC_startTime':bean class [[=75] 的 属性 'ALC_startTime' 无效=]$1]: Bean 属性 'ALC_startTime' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of getter setter?
SQL
Delete from SB_STREAM.TT_9321383
WHERE (LASTUPDATESTAMP >= to_timestamp (:ALC_startTime, 'YYYY-MM-DD HH24:MI:SS.FF')
and LASTUPDATESTAMP <= to_timestamp (:ALC_endTime, 'YYYY-MM-DD HH24:MI:SS.FF'))
AND ttkey = BIGINT(:ID)
AND (ttobjectname = :ALC_object AND ttschema = :ALC_schema)
流量:
return flowDef
.filter(getFilterExpression(rule)).channel(new DirectChannel())
.handle(inboundAdapter) // a JdbcOutboundAdapter
.split(insertDeleteSplitter)
.publishSubscribeChannel(taskExecutor, c ->
c.subscribe(s -> s
.filter ("....")
.transform(genericTransformer)
.handle(insertUpdateMessageHandler(rule))) // a JDBCMessageHandler
.subscribe(s -> s
.filter("....")
.transform(genericTransformer)
.handle(deleteMessageHandler(rule))) // a JDBCMessageHandler
.subscribe(sub -> sub
.handle(cleanupMessageHandler(rule))) // a JDBCMessageHandler
.errorHandler(new CustomErrorHandler() //
);
cleanupMessagehandler
private MessageHandler cleanupMessageHandler(RuleMetadata rule) {
<snip ...>
SQLTextAndParamsList sql = sqlFactory.getCleanupSQL(rule);
JdbcMessageHandler handler = new JdbcMessageHandler(dbprx.getDatasource(), sql.getSql());
return handler;
}
JdbcMessageHandler 收到的消息
SQL调用 JDBCOperation 时的 ParameterSources
替代编码 - 调用 JDBCOperation 中值的 batchArray(将 ExpressionEvaluatingSqlParameterSourceFactory 添加到 JdbcMessageHandler)
AbstractNestablePropertyAccessor.getPropertyValue() 处的调试器视图
CachedIntrospectionResults.getPropertyDecriptor() 处的调试器视图
编辑:代码更改
生成的SQL更新为:
Delete from SB_STREAM.TT_9321383
WHERE (LASTUPDATESTAMP >= to_timestamp (:payload[ALC_startTime], 'YYYY-MM-DD HH24:MI:SS.FF')
and LASTUPDATESTAMP <= to_timestamp (:payload[ALC_endTime], 'YYYY-MM-DD HH24:MI:SS.FF'))
AND ttkey = :payload[ID]
AND (ttobjectname = :payload[ALC_object] AND ttschema = :payload[ALC_schema])
根据您的第一个屏幕截图,您消息的有效负载是 ArrayList
,它确实没有那些 ALC_startTime
、ALC_endTime
属性。 ArrayList
!
上没有那些吸气剂
为了能够阅读列表的内容,您需要在 JdbcMessageHandler
上配置 ExpressionEvaluatingSqlParameterSourceFactory
。有关详细信息,请参阅文档:https://docs.spring.io/spring-integration/docs/current/reference/html/jdbc.html#passing-parameters-by-using-spel-expressions.
以某种方式或某种 POJO 表示形式将您的列表转换为 Map
可能更好。使用该列表,您将很难仅通过索引来确定目标值...
编辑:
本次是批量更新,所以地图数组列表是正确的。
SQL 参数中的 SPEl 表达式格式不正确。正确的形式是 :payload[ALC_startTime]
.
症状:
调用时,此子流的 cleanupMessageHandler
组件(JdbcMessageHandler)不会从消息中提取参数,而是尝试从静态 bean 中提取参数。
异常信息:
org.springframework.dao.InvalidDataAccessApiUsageException:没有为 SQL 参数提供值 'ALC_startTime':bean class [[=75] 的 属性 'ALC_startTime' 无效=]$1]: Bean 属性 'ALC_startTime' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of getter setter?
SQL
Delete from SB_STREAM.TT_9321383
WHERE (LASTUPDATESTAMP >= to_timestamp (:ALC_startTime, 'YYYY-MM-DD HH24:MI:SS.FF')
and LASTUPDATESTAMP <= to_timestamp (:ALC_endTime, 'YYYY-MM-DD HH24:MI:SS.FF'))
AND ttkey = BIGINT(:ID)
AND (ttobjectname = :ALC_object AND ttschema = :ALC_schema)
流量:
return flowDef
.filter(getFilterExpression(rule)).channel(new DirectChannel())
.handle(inboundAdapter) // a JdbcOutboundAdapter
.split(insertDeleteSplitter)
.publishSubscribeChannel(taskExecutor, c ->
c.subscribe(s -> s
.filter ("....")
.transform(genericTransformer)
.handle(insertUpdateMessageHandler(rule))) // a JDBCMessageHandler
.subscribe(s -> s
.filter("....")
.transform(genericTransformer)
.handle(deleteMessageHandler(rule))) // a JDBCMessageHandler
.subscribe(sub -> sub
.handle(cleanupMessageHandler(rule))) // a JDBCMessageHandler
.errorHandler(new CustomErrorHandler() //
);
cleanupMessagehandler
private MessageHandler cleanupMessageHandler(RuleMetadata rule) {
<snip ...>
SQLTextAndParamsList sql = sqlFactory.getCleanupSQL(rule);
JdbcMessageHandler handler = new JdbcMessageHandler(dbprx.getDatasource(), sql.getSql());
return handler;
}
JdbcMessageHandler 收到的消息
SQL调用 JDBCOperation 时的 ParameterSources
替代编码 - 调用 JDBCOperation 中值的 batchArray(将 ExpressionEvaluatingSqlParameterSourceFactory 添加到 JdbcMessageHandler)
AbstractNestablePropertyAccessor.getPropertyValue() 处的调试器视图
CachedIntrospectionResults.getPropertyDecriptor() 处的调试器视图
编辑:代码更改
生成的SQL更新为:
Delete from SB_STREAM.TT_9321383
WHERE (LASTUPDATESTAMP >= to_timestamp (:payload[ALC_startTime], 'YYYY-MM-DD HH24:MI:SS.FF')
and LASTUPDATESTAMP <= to_timestamp (:payload[ALC_endTime], 'YYYY-MM-DD HH24:MI:SS.FF'))
AND ttkey = :payload[ID]
AND (ttobjectname = :payload[ALC_object] AND ttschema = :payload[ALC_schema])
根据您的第一个屏幕截图,您消息的有效负载是 ArrayList
,它确实没有那些 ALC_startTime
、ALC_endTime
属性。 ArrayList
!
为了能够阅读列表的内容,您需要在 JdbcMessageHandler
上配置 ExpressionEvaluatingSqlParameterSourceFactory
。有关详细信息,请参阅文档:https://docs.spring.io/spring-integration/docs/current/reference/html/jdbc.html#passing-parameters-by-using-spel-expressions.
以某种方式或某种 POJO 表示形式将您的列表转换为 Map
可能更好。使用该列表,您将很难仅通过索引来确定目标值...
编辑: 本次是批量更新,所以地图数组列表是正确的。
SQL 参数中的 SPEl 表达式格式不正确。正确的形式是 :payload[ALC_startTime]
.