[英]Why does my open ResultSet automatically close after alter session
我们有针对 Oracle 根容器 cdb cdb$root
中的视图打开ResultSet
的代码。 当代码迭代行时,有一个用例我们需要执行特定的 function 调用,但此调用必须在特定可插入数据库的上下文中进行,在我们的例子中ORCLDPB1
。 实际上,代码如下所示:
while (resultSet.next()) {
LOGGER.info("ResultSet Closed (Top Of Loop): {}", resultSet.isClosed());
if (someSpecialUseCaseIsTrue) {
try (Statement s = connection.createStatement()) {
LOGGER.info("ResultSet Closed (Creating new statement): {}", resultSet.isClosed());
try {
s.executeUpdate("ALTER SESSION SET CONTAINER=ORCLPDB1");
LOGGER.info("ResultSet Closed (after alter session): {}", resultSet.isClosed());
// perform some PDB specific operation
}
finally {
s.executeUpdate("ALTER SESSION SET CONTAINER=cdb$root");
LOGGER.info("ResultSet Closed (after alter back to root): {}", resultSet.isClosed());
}
}
}
}
output 是:
ResultSet Closed (Top Of Loop): false
ResultSet Closed (Creating new statement): false
ResultSet Closed (after alter session): true
ResultSet Closed (after alter back to root): true
然后当 while 在第二次迭代中检查resultSet.next()
时,这会产生
java.sql.SQLException: Closed Resultset: next
at oracle.jdbc.driver.InsensitiveScrollableResultSet.ensureOpen(InsensitiveScrollableResultSet.java:133)
at oracle.jdbc.driver.InsensitiveScrollableResultSet.next(InsensitiveScrollableResultSet.java:428)
通过调试,我确定外部ResultSet
保持打开状态,直到ALTER SESSION
被执行,然后立即调用isClosed()
返回外部结果集不再打开。
这种行为是由于在现有ResultSet
打开时执行另一个操作,还是因为正在执行的实际语句,即ALTER SESSION
? 如果是后者,为什么这会强制ResultSet
无效?
来自Oracle“使用 SQL*Plus 管理 CDB”文档:
40.2.3 使用 ALTER SESSION 语句切换到容器
...
以下是使用
ALTER SESSION SET CONTAINER
语句的注意事项:
- ...
- If you open a cursor and use
ALTER SESSION SET CONTAINER
to switch to different container, then you cannot fetch data from that cursor until you switch back to the container in which the cursor was opened.
首先,我检查了 SQL*Plus 中的简单场景 - 它工作正常:
SQL> alter session set container=pdb1;
Session altered.
SQL> create table test as select 1 a from dual;
Table created.
SQL> var c refcursor;
SQL> exec open :c for select * from test;
PL/SQL procedure successfully completed.
SQL> alter session set container=cdb$root;
Session altered.
SQL> alter session set container=pdb1;
Session altered.
SQL> print c
A
----------
1
可以看到我在PDB1中打开cursor,切换到CDB$ROOT,然后返回到PDB1,成功从cursor中获取。
那么你到底在做什么// perform some PDB specific operation
? 有交易吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.