没有为存储过程定义参数@x …使用MS_SQL JDBC

我试图在方法中使用SQL Server JDBC执行存储过程:

//Connection connection, String sp_name, Mapparams input to the method DatabaseMetaData dbMetaData = connection.getMetaData(); HashMap paramInfo = new HashMap(); if (dbMetaData != null) { ResultSet rs = dbMetaData.getProcedureColumns (null, null, sp_name.toUpperCase(), "%"); while (rs.next()) paramInfo.put(rs.getString(4), rs.getInt(6)); rs.close(); } String call = "{ call " + sp_name + " ( "; for (int i = 0; i  0) call = call.substring(0, call.length() - 1); call += " ) }"; CallableStatement st = connection.prepareCall (call); for (String paramName: paramInfo.keySet()){ int paramType = paramInfo.get(paramName); System.out.println("paramName="+paramName); System.out.println("paramTYpe="+paramType); Object paramVal = params.get(paramName); st.setInt(paramName, Integer.parseInt(((String)paramVal))); //All stored proc parameters are of type int } 

假设存储过程名称为ABC ,参数为@a 。 现在DatabaseMetaData返回列名@a但设置st.setInt("@a",0)返回以下错误:

com.microsoft.sqlserver.jdbc.SQLServerException:未为存储过程ABC定义参数@a。

相反,我尝试了这个: st.setInt("a",0)并且它完美地执行了。

现在的问题是我必须动态设置参数,因为我有太多的存储过程和太多的参数,但jdbc给出了错误。

编辑1:

正如在一个答案中指出的那样,我的问题是重复: JDBC中的命名参数 ,我想解释这里的问题不是命名参数或位置参数,而是关于JDBC不能正确处理SQL服务器参数本身或我在调用它时犯了一些错误。

更新2017-10-07:已接受修复此问题的合并请求 ,因此对于版本6.3.4及更高版本,这不再是问题。


是的,不幸的是,对于mssql-jdbc, DatabaseMetaData#getProcedureColumns返回的参数名称与CallableStatement#setInt et接受的名称不匹配 人。 。 如果您认为它是一个bug,那么您应该在GitHub上创建一个问题,并且可能会在将来的版本中修复它。

然而,与此同时,你只需要解决它。 所以,而不是像这样的代码……

 ResultSet rs = connection.getMetaData().getProcedureColumns(null, "dbo", "MenuPlanner", null); while (rs.next()) { if (rs.getShort("COLUMN_TYPE") == DatabaseMetaData.procedureColumnIn) { String inParamName = rs.getString("COLUMN_NAME"); System.out.println(inParamName); } } 

……产生……

 @person @food 

……你需要使用这样的代码……

 boolean isMssqlJdbc = connection.getClass().getName().equals( "com.microsoft.sqlserver.jdbc.SQLServerConnection"); ResultSet rs = connection.getMetaData().getProcedureColumns(null, "dbo", "MenuPlanner", null); while (rs.next()) { if (rs.getShort("COLUMN_TYPE") == DatabaseMetaData.procedureColumnIn) { String inParamName = rs.getString("COLUMN_NAME"); if (isMssqlJdbc && inParamName.startsWith("@")) { inParamName = inParamName.substring(1, inParamName.length()); } System.out.println(inParamName); } } 

……产生……

 person food