新手问题。。。有人能提供PL/SQL存储过程(驻留在数据库Linux服务器中)中向Java程序(在应用程序服务器中)发送数据需要做什么的高级描述吗?
更新1
elrado在下面的回答让我很感动(谢谢!)。我可以看到PL/SQL存储过程只需要将OUT参数设置为REF CURSOR(例如SYS_REFCURSOR)。然后,调用Java例程可以使用这样的东西:
import oracle.jdbc.*;
...
// call stored procedure using SQL92 syntax
CallableStatement cs = conn.prepareCall( "{call myStoredProc (?,?,?,?,?)}" );
// set IN parameters
cs.setString(1, in1var);
cs.setString(2, in2var);
cs.setString(3, in3var);
// register OUT parameters
cs.registerOutParameter(4, Types.VARCHAR);
cs.registerOutParameter(5, OracleTypes.CURSOR);
// execute and retrieve Oracle "ref cursor" as a Java "ResultSet"
cs.execute();
rs = (ResultSet) cs.getObject(5);
// process result
while (rs.next()) {
...
}
// always retrieve ResultSet before OUT parameters
out1var = cs.getInt(4);
问题1:以上看起来可以吗?
我在Oracle的文档中看到(请参见第4-14至4-15页http://isu.ifmo.ru/docs/doc112/java.112/e10589.pdf)我应该使用OracleCallableStatement
而不是CallableStatement
,这样它看起来应该是这样的:
// execute and retrieve Oracle "ref cursor" as a Java "ResultSet"
cs.execute();
rs = {(OracleCallableStatement)cs}.getCursor(5);
问题2:这两种方法都好吗?如果是这样的话,使用一个替代另一个的优点和缺点是什么?
问题3:我不理解第4-15页上关于Oracle 11G数据库的Important
注释:
Unlike in past releases, the cursor associated with a REF CURSOR is not closed when the result set object in which the REF CURSOR was materialized is closed.
这是否意味着cs
关闭时ref cursor
关闭(与之前的数据库版本相反,后者在rs
关闭时关闭ref cursor
)?
如果您想从Oralce PL/SQL过程返回结果集,请使用ref cursor:
http://www.oracle-base.com/articles/misc/UsingRefCursorsToReturnRecordsets.php
Q1:是的,看起来不错,但我还没有测试。第二季度:我相信OracleCallableStatement只是扩展了CallableStatements。两者都很好,但如果可能的话,我会使用Oracle驱动程序来连接和使用Oracle数据库(而不是一些通用驱动程序)。
Q3:我相信您是对的,当您关闭结果集时,光标保持打开状态(我已经有一段时间没有从过程中读取结果集了,所以我不记得什么时候关闭了光标,抱歉。现在我在家,无法访问Oracle数据库和我的工作计算机。)
如果您的数据库框架是spring-jdbc
,您可以尝试使用更多jdbc(在maven central中可用)。通话看起来像
import static org.morejdbc.NamedJdbcCall.call;
import static org.morejdbc.SqlTypes.*;
import org.morejdbc.*;
...
// note: it can be either INTEGER or VARCHAR - you declare one type, but get result via another
Out<Integer> out4 = Out.of(INTEGER);
// you did not declare the structure of cursor result set, so assume it's a single column of VARCHAR
Out<List<String>> out5 = OracleSqlTypes.cursor((rs, rowNum) -> rs.getString(1));
// named parameter binding is used, hence argument declaration order can be any
jdbcTemplate.execute(call("myStoredProc")
.in("in1", in1var)) // note: first argument is pl/sql parameter name
.in("in2", in2var)
.in("in3", in3var)
.out("out4", out4)
.out("out5", out5)); // will close REF_CURSOR automatically
System.out.println("out4 is " + out4.get());
System.out.println("out5 is " + out5.get());
Q2:我已经用驱动程序11.2.0.4
检查了docker图像wnameless/oracle-xe-11g-r2
,OUT参数检索的两个顺序都很好。