首页 > 解决方案 > 为什么我打开的 ResultSet 在更改会话后会自动关闭

问题描述

我们有代码可以ResultSet在 Oracle 根容器中打开一个视图,cdb$root. 当代码迭代行时,有一个用例,我们需要执行一个特定的函数调用,但是这个调用必须在一个特定的可插入数据库的上下文中进行,在我们的例子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());
      }
    }     
  }
}

输出是:

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?如果是后者,为什么这会迫使 aResultSet无效?

标签: javaoraclejdbcojdbc

解决方案


来自Oracle“使用 SQL*Plus 管理 CDB”文档

40.2.3 使用 ALTER SESSION 语句切换到容器

...

以下是使用该ALTER SESSION SET CONTAINER语句的注意事项:

  • ...
  • 如果您打开一个游标并使用ALTER SESSION SET CONTAINER切换到不同的容器,那么您无法从该游标获取数据,直到您切换回打开游标的容器。

推荐阅读