微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决为什么我打开的 ResultSet 在更改会话后自动关闭

我们有针对 Oracle 根容器 ResultSet 中的视图打开 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?如果是后者,为什么这会强制 ResultSet 无效?

解决方法

来自Oracle "Administering a CDB with SQL*Plus" documentation

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

...

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。