Spring SimpleJdbcCall& SQL Server系统存储过程 - 期望参数未提供,但它是?

时间:2015-02-20 01:27:46

标签: java sql-server spring stored-procedures

我已经google了,我已经搜索了StackOverflow,我已经阅读了示例和教程,我已经浏览了Spring JavaDocs和其他文档。我尝试了许多不同的排列。

几乎无论我尝试什么,我都会得到相同或类似的错误,仅仅因为没有提供抱怨的参数而有所不同:

org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback;     
uncategorized SQLException for SQL [{? = call sys.sp_sequence_get_range(?)}]; 
SQL state [S0004]; error code [201]; 
Procedure or function 'sp_sequence_get_range' expects parameter '@range_size',   
which was not supplied.; nested exception is  
com.microsoft.sqlserver.jdbc.SQLServerException: Procedure or function 
'sp_sequence_get_range' expects parameter '@range_size', which was not supplied.

Java代码:

SimpleJdbcCall jdbcCall = new SimpleJdbcCall(dataSource())
        .withProcedureName("sp_sequence_get_range")
        .withoutProcedureColumnMetaDataAccess()         
        .withCatalogName("sys")
        .declareParameters(new SqlParameter("sequence_name", Types.NVARCHAR), new SqlParameter("range_size", Types.BIGINT))

        .withReturnValue();

    MapSqlParameterSource params = new MapSqlParameterSource()
        .addValue("sequence_name", "dbo.M_PRODUCT_PROD_ID_SEQ")
        .addValue("range_size", Integer.valueOf(rangeSize_));

    Map<String, Object> retVals = jdbcCall.execute(params);

存储过程是SQL Server 2012(v 11)sys.sp_sequence_get_range():

https://msdn.microsoft.com/en-us/library/ff878352%28v=sql.110%29.aspx?f=255&MSPPError=-2147217396

我有一个标准的序列定义 - 我不认为这很重要,因为我甚至无法从我的代码到达SP。在SQL Server Studio中,当我这样调用它时SP就可以工作:

EXEC sys.sp_sequence_get_range
@sequence_name = N'dbo.M_PRODUCT_PROD_ID_SEQ'
, @range_size = 500
, @range_first_value = @FirstSeqNum OUTPUT 
, @range_last_value = @LastSeqNum OUTPUT  ;

-- The following statement returns the output values
SELECT
@FirstSeqNum AS FirstVal
, @LastSeqNum AS LastVal;

我写了一个单元测试,其中rangeSize_ == 100;

param类型与MS在其文档中定义的那些匹配。

除非我失明,否则参数名称匹配,并且它们与SP期望的顺序相同。

我正在使用&#34; withoutProcedureColumnMetaDataAccess()&#34;对于这个问题,这是通常建议的补救措施 - 无济于事。

它似乎超越了第一个参数,但拒绝第二个参考?

如果我更改params来源以包含类型:

MapSqlParameterSource params = new MapSqlParameterSource()
        .addValue("sequence_name", "dbo.M_PRODUCT_PROD_ID_SEQ", Types.NVARCHAR)
        .addValue("range_size", BigInteger.valueOf(rangeSize_), Types.BIGINT);

我得到了一个不同的错误:

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The value is not set for the parameter number 1.

这是否意味着我做得更远,我只需要注册一个OUT参数?

建议?

提前致谢。

2 个答案:

答案 0 :(得分:0)

我没有完全达到我想要的决议;我把它递给了另一个提出解决方法的开发者。他没有直接调用系统SP,而是围绕它编写了一个存储的proc包装器,只需要一个参数并返回6个值。我们终于搞定了。它并不漂亮,但它可以正常工作并大幅减少生成序列值所花费的时间。

从他的工作中,我认为答案就是注册所有的参数。总有一天我会绕过这样做,也许会发布一个更好的答案,但是现在我正试图完成这个超过截止日期的项目。

答案 1 :(得分:0)

我知道回答还很晚,但是可以按以下方式调用SP:

public Long getStartingSequenceNumber(String sequenceName, Long incrementBy) throws SQLException {
Connection con = dataSource.getConnection();
CallableStatement cstmt = null;

try {
  cstmt = con.prepareCall(
      "{call sys.sp_sequence_get_range(?, ?, ?)}");

  cstmt.setString("sequence_name", sequenceName);
  cstmt.setLong("range_size",incrementBy);
  cstmt.registerOutParameter("range_first_value", microsoft.sql.Types.SQL_VARIANT);
  cstmt.execute();
  return cstmt.getLong("range_first_value");
}finally {
  if (cstmt != null) {
    cstmt.close();
  }
}

}