在Linux上使用JDBC从Java中间层调用Oracle PL / SQL存储过程?

时间:2012-03-03 20:02:07

标签: jdbc plsql

新手问题......任何人都可以提供对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.

这是否意味着ref cursorcs关闭时关闭(与以前的数据库版本相反,而当ref cursor关闭时关闭rs?)

2 个答案:

答案 0 :(得分:4)

如果要从Oralce PL / SQL过程返回结果集,请使用ref cursor:

http://www.oracle-base.com/articles/misc/UsingRefCursorsToReturnRecordsets.php

Q1:是的,看起来不错,但我没有测试过。 的 Q2: 我相信OracleCallableStatement只是扩展了CallableStatement。两者都很好,但是在可能的情况下我使用Oracle驱动程序连接并使用Oracle db(而不是一些通用驱动程序)。

问题3:我相信你是对的,当你关闭结果集时,光标会保持打开状态。(自从我从程序中读取结果集以来已经有一段时间了,所以我不记得何时关闭光标对不起现在我在家,无法访问Oracle数据库和我的工作计算机。)

答案 1 :(得分:0)

如果您的数据库框架是spring-jdbc,则可以尝试使用morejdbc(在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:我已经使用驱动程序wnameless/oracle-xe-11g-r2检查了docker image 11.2.0.4,两个OUT参数检索顺序都很好。