繁体   English   中英

为什么我打开的 ResultSet 在更改 session 后会自动关闭

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM