I am trying to execute a stored procedure using SQL Server JDBC in a method:
//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
}
Let say the stored procedure name is ABC
and parameter is @a
.
Now DatabaseMetaData
returns column name @a
but setting st.setInt("@a",0)
returns following error:
com.microsoft.sqlserver.jdbc.SQLServerException: Parameter @a was not defined for stored procedure ABC.
Instead, I tried this: st.setInt("a",0)
and it executed perfectly.
Now the problem is I have to set the parameters dynamically as I have too many stored procedures and too many parameters but jdbc is giving error.
Edit 1:
As pointed out in one answer that my question is a duplicate of: Named parameters in JDBC, I would like to explain that the issue here is not named parameters or positional ones, rather it is about JDBC not handling the SQL server parameters itself properly or my making some error while invoking it.
Update 2017-10-07: The merge request to fix this issue has been accepted, so this should no longer be a problem with versions 6.3.4 and later.
Yes, it is an unfortunate inconsistency that for mssql-jdbc the parameter names returned by
DatabaseMetaData#getProcedureColumns
do not match the names accepted byCallableStatement#setInt
et. al.. If you consider it to be a bug then you should create an issue on GitHub and perhaps it will be fixed in a future release.In the meantime, however, you'll just have to work around it. So, instead of code like this ...
... which produces ...
... you'll need to use code like this ...
... which produces ...