如何使用Spring SimpleJdbcCall调用Apache Derby存储过程并解决解析错误问题
如何使用Spring SimpleJdbcCall调用Apache Derby存储过程并解决解析错误问题
嘿,我之前也踩过这个坑!问题核心在于Apache Derby不支持Spring SimpleJdbcCall默认生成的参数名 => ?这种命名参数调用语法,它只认位置参数的调用格式,所以才会触发解析错误。咱们一步步来解决:
问题根源
Spring的SimpleJdbcCall默认会尝试用命名参数的方式生成调用语句,也就是你看到的[{call EMPLOYEE_TIME_BY_ID(ID => ?)}],但Derby的存储过程调用语法不支持这种写法,它只接受{call 存储过程名(参数1, 参数2...)}这种位置参数形式。
解决方案一:关闭命名参数功能,改用位置参数绑定
你可以通过关闭元数据自动访问的方式,让Spring生成Derby能识别的位置参数调用语句:
// 初始化SimpleJdbcCall SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate) .withProcedureName("EMPLOYEE_TIME_BY_ID") .withoutProcedureColumnMetaDataAccess() // 关键:关闭元数据自动获取,避免生成命名参数语法 .declareParameters(new SqlParameter("ID", Types.INTEGER)); // 声明输入参数 // 调用存储过程,注意参数顺序要和存储过程定义一致 Map<String, Object> params = new HashMap<>(); params.put("ID", 123); // 这里的键名仅用于绑定,实际按位置传递 Map<String, Object> result = jdbcCall.execute(params); // 或者更直接的数组传参,完全按位置匹配 // Map<String, Object> result = jdbcCall.execute(123);
配置后,Spring会生成[{call EMPLOYEE_TIME_BY_ID(?)}]这种Derby能正确解析的调用语句。
解决方案二:手动指定符合Derby语法的调用字符串
如果你需要更灵活的控制,可以直接手动指定调用SQL,绕过Spring的自动生成逻辑:
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate) .withProcedureName("EMPLOYEE_TIME_BY_ID") .withCallString("{call EMPLOYEE_TIME_BY_ID(?)}"); // 手动指定Derby兼容的调用语句 // 调用方式和之前一致 Map<String, Object> params = new HashMap<>(); params.put("ID", 123); Map<String, Object> result = jdbcCall.execute(params);
这种方式更直接,完全由你控制调用语句的格式,不用担心Spring生成不兼容的语法。
额外注意事项
- 不管用哪种方式,参数顺序一定要和存储过程定义的参数顺序完全一致,因为Derby是按位置识别参数的。
- 如果你的存储过程有输出参数或者返回结果集,记得用
SqlOutParameter或SqlInOutParameter正确声明参数类型。
备注:内容来源于stack exchange,提问作者Robert White
相关产品推荐
相关产品推荐

