在Linux上使用JDBC从java中间层调用OraclePL/SQL存储过程



新手问题。。。有人能提供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参数检索的两个顺序都很好。

最新更新