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

在Linux上使用JDBC从java中间层调用Oracle PL/SQL存储过程?,jdbc,plsql,Jdbc,Plsql,新手问题。。。任何人都可以提供一个高级描述,说明在PL/SQL存储过程(驻留在数据库Linux服务器中)中需要执行哪些操作才能将数据发送到Java程序(在应用服务器中) 更新1 下面埃尔拉多的回答让我前进了一步(谢谢!)。我可以看到PL/SQL存储过程只需要将OUT参数设置为REF CURSOR(例如SYS_REFCURSOR)。然后,调用Java例程可以使用如下内容: 导入oracle.jdbc.*; ... //使用SQL92语法调用存储过程 CallableStatement cs=con

新手问题。。。任何人都可以提供一个高级描述,说明在PL/SQL存储过程(驻留在数据库Linux服务器中)中需要执行哪些操作才能将数据发送到Java程序(在应用服务器中)

更新1

下面埃尔拉多的回答让我前进了一步(谢谢!)。我可以看到PL/SQL存储过程只需要将OUT参数设置为REF CURSOR(例如SYS_REFCURSOR)。然后,调用Java例程可以使用如下内容:

导入oracle.jdbc.*; ... //使用SQL92语法调用存储过程 CallableStatement cs=conn.prepareCall(“{call myStoredProc(?,,,,,?)}”); //设定参数 cs.setString(1,in1var); cs.setString(2,in2var); cs.setString(3,in3var); //注册输出参数 registerOutParameter(4,Types.VARCHAR); registerOutParameter(5,OracleTypes.CURSOR); //作为Java“结果集”执行并检索Oracle“ref cursor” cs.execute(); rs=(ResultSet)cs.getObject(5); //过程结果 while(rs.next()){ ... } //始终在输出参数之前检索结果集 out1var=cs.getInt(4); 问题1:上面的看起来可以吗

我在Oracle的文档(见第4-14页至第4-15页)中看到,我应该使用
OracleCallableStatement
而不是
CallableStatement
,因此它应该如下所示:

//将Oracle“ref cursor”作为Java“ResultSet”执行和检索
cs.execute();
rs={(OracleCallableStatement)cs}.getCursor(5);
问题2:两种方法都可以吗?如果是这样的话,使用其中一个的优点和缺点是什么

问题3:我不理解第4-15页关于Oracle 11G数据库的
重要说明:

与以前的版本不同,当REF游标具体化的结果集对象关闭时,与REF游标关联的游标不会关闭。


这是否意味着当关闭
cs
ref游标
将关闭(与以前的数据库版本相反,以前的数据库版本在关闭
rs
时关闭
ref游标

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

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


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

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

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


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

如果你的数据库框架是
spring jdbc
,您可以尝试使用(在maven central中提供)。这个电话看起来像

import static org.morejdbc.NamedJdbcCall.call;
导入静态org.morejdbc.SqlTypes.*;
导入org.morejdbc.*;
...
//注意:它可以是INTEGER或VARCHAR-您声明一种类型,但通过另一种类型获得结果
Out out4=Out.of(整数);
//您没有声明游标结果集的结构,因此假设它是VARCHAR的单个列
out5=OracleSqlTypes.cursor((rs,rowNum)->rs.getString(1));
//使用命名参数绑定,因此参数声明顺序可以是任意的
jdbcTemplate.execute(调用(“myStoredProc”)
.in(“in1”,in1var))//注意:第一个参数是pl/sql参数名
.in(“in2”,in2var)
.in(“in3”,in3var)
.out(“out4”,out4)
.out(“out5”,out5));//将自动关闭参考光标
System.out.println(“out4是”+out4.get());
System.out.println(“out5是”+out5.get());

问题2:我已经检查了docker image
wnameless/oracle-xe-11g-r2
和驱动程序
11.2.0.4
,两种参数检索顺序都很好。

如果您的数据库框架是
spring jdbc
,您可以尝试使用(在maven central中提供)。这个电话看起来像

import static org.morejdbc.NamedJdbcCall.call;
导入静态org.morejdbc.SqlTypes.*;
导入org.morejdbc.*;
...
//注意:它可以是INTEGER或VARCHAR-您声明一种类型,但通过另一种类型获得结果
Out out4=Out.of(整数);
//您没有声明游标结果集的结构,因此假设它是VARCHAR的单个列
out5=OracleSqlTypes.cursor((rs,rowNum)->rs.getString(1));
//使用命名参数绑定,因此参数声明顺序可以是任意的
jdbcTemplate.execute(调用(“myStoredProc”)
.in(“in1”,in1var))//注意:第一个参数是pl/sql参数名
.in(“in2”,in2var)
.in(“in3”,in3var)
.out(“out4”,out4)
.out(“out5”,out5));//将自动关闭参考光标
System.out.println(“out4是”+out4.get());
System.out.println(“out5是”+out5.get());

问题2:我已经检查了docker image
wnameless/oracle-xe-11g-r2
和driver
11.2.0.4
,两个参数检索顺序都很好。

谢谢elrado。这令人困惑。一些示例,如上面的链接,使用
execute()
语句,以及OracleCallableStatement和getCursor。其他链接不使用<