【问题标题】:Calling Oracle PL/SQL stored procedure from java middle tier using JDBC on Linux?在 Linux 上使用 JDBC 从 Java 中间层调用 Oracle PL/SQL 存储过程?
【发布时间】:2012-03-21 21:45:43
【问题描述】:

新手问题...任何人都可以提供关于在 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 cursor 在cs 关闭时关闭(与之前的数据库版本相反,在rs 关闭时ref cursor 关闭)?

【问题讨论】:

    标签: jdbc plsql


    【解决方案1】:

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

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

    Q1:是的,它看起来没问题,但我没有测试过。 第二季度: 我相信 OracleCallableStatement 只是扩展了 CallableStatement。两者都很好,但我尽可能使用 Oracle 驱动程序连接和使用 Oracle db(而不是一些通用驱动程序)。

    Q3:我相信你是对的,当你关闭结果集时光标保持打开状态。(我已经有一段时间没有从过程中读取结果集了,所以我不记得我什么时候关闭光标了抱歉。现在我在家,无法访问 Oracle db 和我的工作计算机。)

    【讨论】:

    • 谢谢埃尔拉多。这很令人困惑。一些示例,如您上面的链接,使用 execute() 语句以及 OracleCallableStatement 和 getCursor。其他链接不使用ref cursor,而是使用executeQuery() 语句和CallableStatement(请参阅此链接的最后一部分:docs.oracle.com/javase/tutorial/jdbc/basics/… 以及:java2s.com/Code/Java/Database-SQL-JDBC/…)。还有其他示例使用 ref cursor 和 executeQuery() 语句,以及 CallableStatement 和 getObject()。
    • @ggkmath 你想出了什么:)。
    • 嗨 elrado,我刚刚第一次尝试它,它工作正常。感谢您对上面 ref cursor 的提示,我能够取得这一进展。感谢您花时间提交答案!这对我帮助很大!
    【解决方案2】:

    如果你的数据库框架是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:我用驱动程序11.2.0.4检查了docker镜像wnameless/oracle-xe-11g-r2,两个OUT参数检索顺序都很好。

    【讨论】:

      猜你喜欢
      • 2017-04-13
      • 2014-06-09
      • 2022-01-18
      • 2015-11-15
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 2014-05-11
      相关资源
      最近更新 更多