首页 > 解决方案 > Simplejdbccall 存储过程 withNamedBinding true

问题描述

我想用 SimpleJdbcCall 执行带有动态参数的存储过程。在 SQL Server SP 中,我总共有 6 个可选参数,其中我必须能够传递任何一个或一个都不传递。我的 SP 在 MS Studio 中按预期执行。但不是 SimpleJdbcCall。我尝试了很多方法,其中一种方法是 withNamedBinding。但它在“=”附近给出了输入语法错误,如下所示。

this.simpleJdbcCall = new SimpleJdbcCall(jdbcTemplateObject)
                    .withNamedBinding()
                    .withSchemaName("dbo")
                    .withProcedureName("EmployeeDetails")
                    .useInParameterNames(
                            paramNameArray)
                    .returningResultSet("detailReportData", BeanPropertyRowMapper.newInstance(Employee.class));
            Map<String,Object> out = this.simpleJdbcCall.execute(sqlSource);

日志:

2019-01-31 18:14:49 调试 SimpleJdbcCall:405 - 以下参数用于调用 {call dbo.EmployeeDetails(empCode => ?, empName => ?, empLoc => ?)} 与 {empCode=0, empName='hgkghdkgf', empLoc='kjhjk'} 2019-01-31 18:14:49 DEBUG DispatcherServlet:993 - 无法完成请求 org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; SQL [{call dbo.EmployeeDetails(empCode => ?, empName => ?, empLoc => ?)}] 的未分类 SQLException;SQL状态[S0001];错误代码[102];'=' 附近的语法不正确。;嵌套异常是 com.microsoft.sqlserver.jdbc.SQLServerException:“=”附近的语法不正确。

标签: sql-serverspring-jdbcsimplejdbccall

解决方案


我遇到过类似类型的问题,但在这个堆栈溢出问题中几乎没有找到解决方案。但就我而言,我使用的是 MS-SQL 服务器,它给了我同样的语法错误。在搜索解决方案时,我遇到了这个Spring 示例(参见第11.5.6 节。声明用于 SimpleJdbcCall 的参数)。以防万一链接不可用,这就是它所说的

我们可以选择显式声明一个、部分或全部参数。参数元数据仍在使用中。通过调用 withoutProcedureColumnMetaDataAccess 方法,我们可以指定我们希望绕过对潜在参数的元数据查找的任何处理,并且只使用已声明的参数。可能出现的另一种情况是一个或多个 in 参数具有默认值,我们希望将它们排除在调用之外。为此,我们只需调用 useInParameterNames 来指定要包含的 in 参数名称列表。

这是示例代码

public class JdbcActorDao implements ActorDao {
private SimpleJdbcCall procReadActor;

public void setDataSource(DataSource dataSource) {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    jdbcTemplate.setResultsMapCaseInsensitive(true);
    this.procReadActor =
            new SimpleJdbcCall(jdbcTemplate)
                    .withProcedureName("read_actor")
                    .withoutProcedureColumnMetaDataAccess()
                    .useInParameterNames("in_id")
                    .declareParameters(
                            new SqlParameter("in_id", Types.NUMERIC),
                            new SqlOutParameter("out_first_name", Types.VARCHAR),
                            new SqlOutParameter("out_last_name", Types.VARCHAR),
                            new SqlOutParameter("out_birth_date", Types.DATE)
                    );
}


//  ... additional methods

}

我不知道为什么,但是 withNamedBinding() 方法似乎无法与 ms-sql 服务器正常工作并产生语法错误。所以在上述解决方案中,解决方法是

  1. 不要使用 .withNamedBinding() 方法。
  2. 使用 .withoutProcedureColumnMetaDataAccess() 方法。
  3. 在将参数数组传递给 .useInParameterNames() 方法时,请确保按照它在 proc 中声明的顺序传递它(因为我们没有使用名称绑定)。我的输出参数在最后一个参数之前声明了几个参数,因此在将 var 转换为 int 时出现错误,因为我的输出参数是 int。

所以现在你的解决方案应该是这样的:

this.simpleJdbcCall = new SimpleJdbcCall(jdbcTemplateObject)
                .withSchemaName("dbo")
                .withProcedureName("EmployeeDetails")
                .withoutProcedureColumnMetaDataAccess()
                .useInParameterNames(paramNameArray)
                .returningResultSet("detailReportData", BeanPropertyRowMapper.newInstance(Employee.class));
        Map<String,Object> out = this.simpleJdbcCall.execute(sqlSource);

试一试,看看这是否适合你。


推荐阅读