如何使用JdbcTemplate在Spring中简洁地调用PL/SQL过程并返回其输出变量?

如何使用JdbcTemplate在Spring中简洁地调用PL/SQL过程并返回其输出变量?,spring,plsql,jdbctemplate,Spring,Plsql,Jdbctemplate,这里是甲骨文的新手。我的经验是构建web应用程序,将查询发送到数据库并返回“结果集”,例如在Java中使用Spring和JdbcTemplate 例如,下面是一个带有常规SQL查询的代码示例,使用RowMapper类将结果集的行转换为Java列表: 公共列表findAllWidgets(){ 返回jdbcTemplate.query(“从小部件中选择*,新建WidgetRowMapper()); } 现在我的任务是编写一个调用PL/SQL存储过程的查询。这个过程有两个输入参数(我可以处理它们)

这里是甲骨文的新手。我的经验是构建web应用程序,将查询发送到数据库并返回“结果集”,例如在Java中使用Spring和JdbcTemplate

例如,下面是一个带有常规SQL查询的代码示例,使用
RowMapper
类将结果集的行转换为Java列表:

公共列表findAllWidgets(){
返回jdbcTemplate.query(“从小部件中选择*,新建WidgetRowMapper());
}
现在我的任务是编写一个调用PL/SQL存储过程的查询。这个过程有两个输入参数(我可以处理它们)和两个输出参数(让我们称它们为
error\u code
error\u message
)。我想向数据库发送一个查询,该数据库将(a)使用我的输入运行该过程,(b)返回两个输出。我同样乐意将这两个输出作为一个“行”,或者简单地将它们绑定到两个Java变量

这是我尝试过的,它没有抛出错误,但也没有得到输出值。Java变量
errorCode
errorMessage
仍然是空字符串:

publicmap callMyProcedure(){
字符串errorCode=“”;
字符串errorMessage=“”;
更新(“调用myprocedure(?,,,,?)”、“input1”、“input2”、错误代码、错误消息);
返回映射(“errorCode”,errorCode,“errorMessage”,errorMessage);
}
问题是:当使用JdbcTemplate从Java调用过程时,如何捕获PL/SQL过程的“OUT”变量的值?


编辑:我接受了Alex的答案,这个答案没有使用JdbcTemplate,因为这似乎是更好的方法。我自己的答案确实使用了JdbcTemplate,但需要更多的代码,因此,如果您正在搜索能够明确回答问题的内容,就可以了。

我从一个网站上找到了一些指导,并提出了以下怪胎:

publicmap callMyProcedure(){
返回jdbcTemplate.call(新的CallableStatementCreator(){
@凌驾
公共CallableStatement createCallableStatement(连接)引发SQLException{
CallableStatement cs=connection.prepareCall({callmyprocedure(?,,,,,,,,,,,,,?)});
cs.setString(1,“foo”);
cs.固定管柱(2,“巴”);
cs.setString(3,“baz”);
cs.setString(4,“威士忌”);
cs.setString(5,“探戈”);
cs.setString(6,“狐步舞”);
registerOutParameter(7,Types.VARCHAR);
registerOutParameter(8,Types.VARCHAR);
返回cs;
}
},Arrays.asList(
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlOutParameter(“errorCode”,Types.VARCHAR),
新的SqlOutParameter(“errorMessage”,Types.VARCHAR)
));
}

它确实有效,但我正在寻找一个能更简洁地做同样事情的答案。也许Spring在那个老答案之后的几年里为JdbcTemplate添加了一个新接口

我从一位专家那里找到了一些指导,并想出了这个怪物:

publicmap callMyProcedure(){
返回jdbcTemplate.call(新的CallableStatementCreator(){
@凌驾
公共CallableStatement createCallableStatement(连接)引发SQLException{
CallableStatement cs=connection.prepareCall({callmyprocedure(?,,,,,,,,,,,,,?)});
cs.setString(1,“foo”);
cs.固定管柱(2,“巴”);
cs.setString(3,“baz”);
cs.setString(4,“威士忌”);
cs.setString(5,“探戈”);
cs.setString(6,“狐步舞”);
registerOutParameter(7,Types.VARCHAR);
registerOutParameter(8,Types.VARCHAR);
返回cs;
}
},Arrays.asList(
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlParameter(Types.VARCHAR),
新的SqlOutParameter(“errorCode”,Types.VARCHAR),
新的SqlOutParameter(“errorMessage”,Types.VARCHAR)
));
}

它确实有效,但我正在寻找一个能更简洁地做同样事情的答案。也许Spring在那个老答案之后的几年里为JdbcTemplate添加了一个新接口

您可以在
jdbcTemplate
下获取连接,并使用get方法获取输出,如下所示:

以Java编程语言中的字符串形式检索指定的NCHAR、NVARCHAR或LONGNVARCHAR参数的值


您可以在
jdbcTemplate
下获取连接,并使用get方法获取输出,如下所示

以Java编程语言中的字符串形式检索指定的NCHAR、NVARCHAR或LONGNVARCHAR参数的值


您可以使用普通JDBC

final String charlie;
final String zulu;
try (CallableStatement cs = connection.prepareCall("{call myprocedure(?,?,?,?,?,?,?,?)}")) {
    cs.setString(1, "foo");
    cs.setString(2, "bar");
    cs.setString(3, "baz");
    cs.setString(4, "whisky");
    cs.setString(5, "tango");
    cs.setString(6, "foxtrot");
    cs.registerOutParameter(7, Types.VARCHAR);
    cs.registerOutParameter(8, Types.VARCHAR);
    cs.execute();
    connection.commit(); // optional
    charlie = cs.getString(7);
    zulu = cs.getString(8);
}

在使用JDBC时,使用
getInt
方法和类似的方法是危险的,因为它们将类型转换为基元,并且将0替换为0。最好使用
(整数)cs.getObject()
。类似地,
setInt
不支持引用类型。

您可以使用普通JDBC

final String charlie;
final String zulu;
try (CallableStatement cs = connection.prepareCall("{call myprocedure(?,?,?,?,?,?,?,?)}")) {
    cs.setString(1, "foo");
    cs.setString(2, "bar");
    cs.setString(3, "baz");
    cs.setString(4, "whisky");
    cs.setString(5, "tango");
    cs.setString(6, "foxtrot");
    cs.registerOutParameter(7, Types.VARCHAR);
    cs.registerOutParameter(8, Types.VARCHAR);
    cs.execute();
    connection.commit(); // optional
    charlie = cs.getString(7);
    zulu = cs.getString(8);
}
在使用JDBC时,使用
getInt
方法和类似的方法是危险的,因为它们将类型转换为基元,并且将0替换为0。最好使用
(整数)cs.getObject()
。类似地,
setInt
不支持引用类型。