MySql 函数的 SimpleJdbcCall 产生 "Can't set IN parameter for return value of stored function call"
SimpleJdbcCall for MySql Function yields "Can't set IN parameter for return value of stored function call"
使用 Spring 文档中的示例,我尝试 return 来自 mySQL 函数的值。我一直收到错误 Can't set IN parameter for return value of stored function call;
.
我创建了一个工作正常的 mySQL 函数(运行 in MySQL Workbench)。我写了一个 SimpleJdbcCall
语句,按照 Spring 文档示例设置参数,但始终出现此错误。如果我把这个函数变成一个过程,代码就可以工作,我只需要从结果集中检索 return 值。
我使用了 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 then
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.
我觉得有趣的是,它采用了我的三个输入值并将它们更改为一个输出值和两个输入值。
有人告诉我这个问题以及如何解决吗?
谢谢,
史蒂文。
我会参考 latest docs here 来回答你的问题。似乎 Spring 正在尝试推断输出,因为您没有明确指定一个。
根据上面的文档,有两种使用 SimpleJdbcCall
:
调用所需函数的有效方法
推断参数
因为您指定了 withoutProcedureColumnMetaDataAccess
,Spring 不会查看 ins/outs 对您的函数的作用。如果你想要它简单,只是不指定,你应该能够做到:
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);
使用 Spring 文档中的示例,我尝试 return 来自 mySQL 函数的值。我一直收到错误 Can't set IN parameter for return value of stored function call;
.
我创建了一个工作正常的 mySQL 函数(运行 in MySQL Workbench)。我写了一个 SimpleJdbcCall
语句,按照 Spring 文档示例设置参数,但始终出现此错误。如果我把这个函数变成一个过程,代码就可以工作,我只需要从结果集中检索 return 值。
我使用了 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 then
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.
我觉得有趣的是,它采用了我的三个输入值并将它们更改为一个输出值和两个输入值。
有人告诉我这个问题以及如何解决吗?
谢谢,
史蒂文。
我会参考 latest docs here 来回答你的问题。似乎 Spring 正在尝试推断输出,因为您没有明确指定一个。
根据上面的文档,有两种使用 SimpleJdbcCall
:
推断参数
因为您指定了 withoutProcedureColumnMetaDataAccess
,Spring 不会查看 ins/outs 对您的函数的作用。如果你想要它简单,只是不指定,你应该能够做到:
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);