使用从Spring文档的例子中,我试图从一个MySQL函数返回一个值。我不断收到错误Can't set IN parameter for return value of stored function call;
。
我创建一个MySQL函数(在MySQL工作台RAN)工作正常。我写了一个SimpleJdbcCall
语句,按照Spring docs示例设置了参数,但是始终出现此错误。如果将函数转换为过程,则代码可以正常工作,我只需要从结果集中检索返回值即可。
我用https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch13s05.html,部分13.5.8作为参考。
CREATE FUNCTION `ScenarioRegistration`(
environment VARCHAR(45),
username VARCHAR(15),
scenario_name VARCHAR(45)) RETURNS int(11)
几个SELECT语句,然后是INSERT
RETURN scenario_id; // The inserted id
Java代码:
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess();
simpleJdbcCall.addDeclaredParameter(new SqlParameter("environment"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("username"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("scenario_name"
,Types.VARCHAR));
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
simpleJdbcCall.setReturnValueRequired(true);
Integer scenario_id = simpleJdbcCall.executeFunction(
Integer.class, parameters);
我要让例程执行的所有操作是给我返回新插入的方案的ID。
我得到的是:
SQL [{? = call scenarioregistration(?, ?)}]; Can't set IN parameter for return value of stored function call.
我觉得很有趣,它已使用了三个输入值并将它们更改为一个输出和两个输入值。
任何人指教我的问题,以及如何解决它?
谢谢
史蒂芬。
答案 0 :(得分:2)
对于您的答案,我会参考latest docs here。似乎Spring试图推断输出,因为您没有明确指定输出。
根据以上文档,使用SimpleJdbcCall
调用所需函数有两种有效方法:
推断的参数
由于您已指定withoutProcedureColumnMetaDataAccess
,因此Spring不会查看并查看函数的内容。如果您想轻松一点,只需不指定它,就可以做到:
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.executeFunction(Integer.class, parameters);
显式参数
如果出于某种原因要关闭withoutProcedureColumnMetaDataAccess
,则可以执行以下操作:
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate)
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("environment", "username", "scenario_name")
.declareParameters(
new SqlOutParameter("scenario_id", Types.NUMERIC),
new SqlParameter("environment", Types.VARCHAR),
new SqlParameter("username", Types.VARCHAR),
new SqlParameter("scenario_name", Types.VARCHAR)
).executeFunction(Integer.class, parameters);
注意:在此示例中,顺序似乎是关键。 output
参数应首先声明,随后命名的IN
参数应最后声明。也就是说,参数?
的顺序在[{? = call scenarioregistration(?, ?, ?)}]
中是顺序的)
备用NamedParameterJdbcTemplate
解决方案
另一种调用函数的方法是通过实际的JDBC调用。据推测,这可以节省您对SimpleJdbcCall
进行微调的麻烦。
Integer scenarioId = namedParameterJdbcTemplate.queryForObject(
"SELECT ScenarioRegistration(:environment, :username, :scenario_name)",
parameters,
Integer.class);