使用 StoredProcedureItemReader 时出现 SQLServerException

SQLServerException when using StoredProcedureItemReader

我在尝试使用 StoredProcedureItemReader 时遇到错误。

我有一个用 Microsoft SQL 服务器编写的存储过程,它具有以下输入和输出参数:
存储过程名称: person_details
输入: @From,@To
输出是来自不同表的不同列的组合。

这是我的代码:

    StoredProcedureItemReader<ClaimExtractDTO> reader = new StoredProcedureItemReader<>();

    SqlParameter[] parameter = {new SqlParameter("@From", java.sql.Types.BIGINT), new SqlParameter("@To", java.sql.Types.BIGINT)};

    PreparedStatementSetter statementValues = new PreparedStatementSetter() {
        @Override
        public void setValues(PreparedStatement ps) throws SQLException {
            ps.setLong(1, minValue); //minValue - Input 1
            ps.setLong(2, maxValue); //maxValue - Input 2
        }
    };  
    reader.setDataSource(dataSource);
    reader.setProcedureName("dbo.person_details");
    reader.setParameters(parameter);
    reader.setPreparedStatementSetter(statementValues);
    reader.setRowMapper(new BeanPropertyRowMapper<>(ClaimExtractDTO.class));    
    return reader;

当运行上面的代码我得到

Caused by: org.springframework.dao.TransientDataAccessResourceException: Executing stored procedure; SQL [{call dbo.person_details(?, ?)}]; The index 0 of the output parameter is not valid.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The index 0 of the output parameter is not valid.
    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:110) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:229) ~[spring-batch-infrastructure-4.2.3.BUILD-SNAPSHOT.jar:4.2.3.BUILD-SNAPSHOT]
    at org.springframework.batch.item.database.AbstractCursorItemReader.doOpen(AbstractCursorItemReader.java:428) ~[spring-batch-infrastructure-4.2.3.BUILD-SNAPSHOT.jar:4.2.3.BUILD-SNAPSHOT]
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:150) ~[spring-batch-infrastructure-4.2.3.BUILD-SNAPSHOT.jar:4.2.3.BUILD-SNAPSHOT]
    ... 18 common frames omitted
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The index 0 of the output parameter is not valid.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:234) ~[mssql-jdbc-7.4.1.jre8.jar:na]
    at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getterGetParam(SQLServerCallableStatement.java:403) ~[mssql-jdbc-7.4.1.jre8.jar:na]
    at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getObject(SQLServerCallableStatement.java:705) ~[mssql-jdbc-7.4.1.jre8.jar:na]
    at com.zaxxer.hikari.pool.HikariProxyCallableStatement.getObject(HikariProxyCallableStatement.java) ~[HikariCP-3.4.5.jar:na]
    at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:222) ~[spring-batch-infrastructure-4.2.3.BUILD-SNAPSHOT.jar:4.2.3.BUILD-SNAPSHOT]
    ... 20 common frames omitted

当我 运行 使用 exec dbo.person_details '1', '100'; 服务器上的 SQL 存储过程时,它 运行 很好,并让我得到由来自不同表的 20 列组成的输出.

我什至在程序上设置了set nocount on

我用 SqlParameter[] parameter = {new SqlOutParameter("personKey", java.sql.Types.INTEGER), new SqlParameter("@From", java.sql.Types.BIGINT), new SqlParameter("@To", java.sql.Types.BIGINT)}; 尝试过,认为应该定义外参数。我仍然遇到与上述相同的错误。

程序主要内容:

USE [employee]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
set nocount on
GO

ALTER PROCEDURE [dbo].[person_details]
@From   BIGINT,
@To     BIGINT
AS
....

谁能告诉我如何解决这个问题。提前致谢!

您需要确保在存储过程本身中设置 SET NOCOUNT ON 以避免此错误。不需要输出参数,但行数作为一个返回。

你又是运行直接存储程序SQL服务器如下:

exec dbo.person_details '1', '100';

即两个输入参数,没有输出参数。

然而在您的代码中,您设置的参数如下:

SqlParameter[] parameter = {new SqlOutParameter("personKey", java.sql.Types.INTEGER), new SqlParameter("@From", java.sql.Types.BIGINT), new SqlParameter("@To", java.sql.Types.BIGINT)};

即一个输出参数和两个输入参数。

在我将 set nocount on 放入我的程序后它起作用了

USE [employee]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[person_details]
@From   BIGINT,
@To     BIGINT
AS
set nocount on;

我的 SQLParameters 看起来像

SqlParameter[] parameter = {new SqlParameter("@From", java.sql.Types.BIGINT), new SqlParameter("@To", java.sql.Types.BIGINT)};