Spring调用存储过程报Parameter number 2 is not an OUT parameter错误
问题:Spring调用MySQL存储过程报错“Parameter number 2 is not an OUT parameter”
错误日志
ERROR | 2024-02-28 12:43:23 | [http-/127.0.0.1:8881-1] impl.ProductDAOImpl (ProductDAOImpl.java:702) - Exception caught for getStockCount Parameter number 2 is not an OUT parameter java.sql.SQLException: Parameter number 2 is not an OUT parameter at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63) at com.mysql.cj.jdbc.CallableStatement.checkIsOutputParam(CallableStatement.java:643) at com.mysql.cj.jdbc.CallableStatement.registerOutParameter(CallableStatement.java:1714) at com.mysql.cj.jdbc.CallableStatement.registerOutParameter(CallableStatement.java:1722)
场景说明
直接在MySQL数据库中调用存储过程calculate_stock_count可正常执行;同一代码逻辑调用其他存储过程无异常,但调用该存储过程时,错误出现在callStmt.registerOutParameter(2, java.sql.Types.INTEGER);行。
相关代码
public Integer getStockCount(String partNumber){ Integer stockCount = null; String query = "{CALL calculate_stock_count(?, ?)}"; Connection connection = null; CallableStatement callStmt = null; try { connection = this.jdbcTemplate.getDataSource().getConnection(); callStmt = connection.prepareCall(query); callStmt.setString(1, partNumber); callStmt.registerOutParameter(2, java.sql.Types.INTEGER); callStmt.execute(); stockCount = callStmt.getInt(2); } catch (SQLException e) { logger.error("Exception caught for getStockCount " + e.getMessage(), e); } finally { try { if(callStmt != null){ callStmt.close(); } if(connection != null){ connection.close(); } } catch (SQLException e) { logger.error("Exception caught in getStockCount while closing the connection" + e.getMessage(), e); } finally{ if(connection != null){ try { connection.close(); } catch (SQLException e) { logger.error("Exception caught in getStockCount while closing the connection" + e.getMessage(), e); } } } } return stockCount; }
错误原因分析
- 存储过程定义不匹配:代码中默认第二个参数是OUT类型,但实际
calculate_stock_count的第二个参数可能不是OUT/INOUT类型,或者参数顺序、数量与代码预期不符。 - 驱动版本兼容性:部分MySQL JDBC驱动版本对存储过程参数的解析存在差异,可能错误识别参数的输入输出类型。
- 调用语法偏差:使用
{CALL ...}格式调用时,占位符需与存储过程定义的参数类型、顺序完全对应,否则会触发参数类型不匹配错误。
解决方法
核对存储过程定义
执行SHOW CREATE PROCEDURE calculate_stock_count;查看参数定义:- 如果第二个参数不是OUT/INOUT类型,而是存储过程通过结果集返回数据,需修改代码逻辑:
callStmt.setString(1, partNumber); ResultSet rs = callStmt.executeQuery(); if(rs.next()){ stockCount = rs.getInt(1); } - 如果参数顺序或数量不符,调整代码中
registerOutParameter的索引值和调用语句的占位符数量。
- 如果第二个参数不是OUT/INOUT类型,而是存储过程通过结果集返回数据,需修改代码逻辑:
验证驱动版本
确保MySQL JDBC驱动版本与服务器版本匹配(如MySQL 8.0对应mysql-connector-java 8.x),避免版本不兼容导致的参数解析问题。优化资源管理
使用try-with-resources语法自动管理连接和Statement,避免重复关闭资源的冗余代码:public Integer getStockCount(String partNumber){ Integer stockCount = null; String query = "{CALL calculate_stock_count(?, ?)}"; try (Connection connection = this.jdbcTemplate.getDataSource().getConnection(); CallableStatement callStmt = connection.prepareCall(query)) { callStmt.setString(1, partNumber); callStmt.registerOutParameter(2, java.sql.Types.INTEGER); callStmt.execute(); stockCount = callStmt.getInt(2); } catch (SQLException e) { logger.error("Exception caught for getStockCount " + e.getMessage(), e); } return stockCount; }
内容的提问来源于stack exchange,提问作者Zohaib Asim
相关产品推荐
相关产品推荐

