参数@x未针对存储过程定义..使用MS_SQL JDBC



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

//Connection connection, String sp_name, Map<String, Object>params input to the method
DatabaseMetaData dbMetaData = connection.getMetaData();
HashMap<String, Integer> paramInfo = new HashMap<String, Integer>();
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 < paramInfo.size(); i ++)
    call += "?,";
if (paramInfo.size() > 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:parameter @a未定义为存储过程ABC。

相反,我尝试了一下:st.setInt("a",0),并且执行完美。

现在问题是我必须动态设置参数,因为我的存储过程太多并且参数太多,但是JDBC正在给出错误。

编辑1:

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

更新2017-10-07:解决此问题的合并请求已被接受,因此版本6.3.4和更高版本不再是问题。


是的,不幸的是,对于MSSQL-JDBC,DatabaseMetaData#getProcedureColumns返回的参数名称与CallableStatement#setInt ET接受的名称不匹配。al。。如果您认为它是一个错误,则应该在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

最新更新