我正在尝试调用PostgreSQL的函数/存储过程(返回游标)。我正在通过Spring Integration的stored-proc-outbound-gateway
调用该函数。它给了我以下错误:
Caused by: org.springframework.messaging.MessageHandlingException: Expression evaluation failed: @sampleProcedureGateway.exchange(#root).payload; nested exception is org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{? = call erb.getSampleDetails_sp(?, ?, ?, ?, ?)}]; SQL state [34000]; error code [0]; ERROR: cursor "<unnamed portal 5>" does not exist; nested exception is org.postgresql.util.PSQLException: ERROR: cursor "<unnamed portal 5>" does not exist
下面是我的Spring Integration配置:
<int:chain input-channel="inputDataChannel">
<int-jdbc:stored-proc-outbound-gateway data-source="dataSource" expect-single-result="true" is-function="true" stored-procedure-name="erb.getSampleDetails_sp" ignore-column-meta-data="true">
<int-jdbc:sql-parameter-definition name="id" direction="IN"/>
<int-jdbc:sql-parameter-definition name="date" direction="IN"/>
<int-jdbc:sql-parameter-definition name="name" direction="IN"/>
<int-jdbc:sql-parameter-definition name="endrow" type="INTEGER" direction="IN"/>
<int-jdbc:sql-parameter-definition name="startrow" type="INTEGER" direction="IN"/>
<int-jdbc:sql-parameter-definition name="finalData" direction="OUT"/>
<int-jdbc:parameter name="id" expression="headers.messageProcessResultHeader.interfaceRequestMetaData.dealerCode"/>
<int-jdbc:parameter name="date" expression="headers['documentDate']"/>
<int-jdbc:parameter name="name" expression="headers['IsRTIDealer']"/>
<int-jdbc:parameter name="endrow" expression="headers['endRow']"/>
<int-jdbc:parameter name="startrow" expression="headers['startRow']"/>
<int-jdbc:returning-resultset name="finalData" row-mapper="sampleRowMapper" />
</int-jdbc:stored-proc-outbound-gateway>
</int:chain>
以下是存储过程:
CREATE OR REPLACE FUNCTION erb.getSampleDetails_sp(
id text,
date text,
name text,
endrow double precision,
startrow double precision,
OUT finalData refcursor)
RETURNS refcursor
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
BEGIN
IF name = 'true' THEN
OPEN finalData FOR
SELECT
*
FROM (SELECT
row_number() OVER (ORDER BY NULL) AS rnum, vhinv.*
FROM (SELECT query) AS vhinv
LIMIT i_endrow) AS var_sbq
WHERE rnum >= i_startrow;
ELSE
OPEN finalData FOR
SELECT
*
FROM (SELECT
row_number() OVER (ORDER BY NULL) AS rnum, vhinv.*
FROM (SELECT query) AS vhinv
LIMIT i_endrow) AS var_sbq_2
WHERE rnum >= i_startrow;
END IF;
END;
$BODY$;
有什么方法可以解决这个问题吗?
答案 0 :(得分:0)
首先,您确实需要确保存储过程确实是函数(is-function="true"
)并且它返回游标。
很高兴看到您的存储过程以确保正确映射所有参数。
Reference Manual中还有一个描述:
指定SQL参数定义的方向。默认为
IN
。有效值包括:IN
,OUT
和INOUT
。如果您的程序正在返回ResultSets
,请使用returning-resultset
元素。可选的。
我的意思是您必须从配置中移除sql-parameter-definition name="finalData"
并依赖returning-resultset name="finalData"
。
答案 1 :(得分:0)
在Datasource bean定义中将autoCommit设置为false后,此问题已得到解决。
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverName);
dataSource.setUrl(dbConnectionUrl);
dataSource.setUsername(userName);
dataSource.setDefaultAutoCommit(false);
dataSource.setEnableAutoCommitOnReturn(false);
答案 2 :(得分:0)
正如Abirmi所述,应同时将MappingJacksonHttpMessageConverter
设置为false来解决此问题,如果要在现有大型应用程序中解决此问题,则应遵循以下方法,而不是对其进行硬编码。因此,我们可以确保仅更改所需流的AutoCommit属性,而不更改所涉及的连接对象的全部操作。
AutoCommit