从 Oracle DB 获取可滚动的结果集

Getting Scrollable Resultsets from Oracle DB

我们的团队与使用 jdbcOracle 数据库服务器紧密合作。在我们的一项更改中,我调用了一个存储过程,它 return 是两个不同的 ResultSets。起初我的实现采用默认的滚动能力。 失败后上网查了一下

我能读到的关于它的所有内容基本上都说了同样的话:使用 prepareStatementprepareCall 方法以及适当的 TYPE_SCROLL_INSENSITIVECONCUR_READ_ONLY。 None 其中有效。

我再次使用存储过程,return 我有两个不同的结果集,它们是通过 (ResultSet) rs.getObject("name") 提取的。通常在示例中,他们的 ResultSet 从 .executeQuery 立即返回。 我的问题是,prepareCall 方法中的 Scrollablility/Updatability 类型会影响这些类型的结果集吗?如果是这样,我如何获得它们?

我知道 JDBC 驱动程序可以降低我对 ScrollableResultSet 的请求。 如何判断我的 ResultSet 是否已降级?

关于这一点,为什么默认情况下 ResultSets 不可滚动?最佳实践是什么?它们的灵活性 "the cost" 是什么?

在 Oracle 中,游标是一个 forward-only 结构。数据库只知道如何获取下一行(好吧,从技术上讲是接下来的 n 行)。为了使 ResultSet 看起来可滚动,您依赖 JDBC driver。

JDBC driver 有两种使 ResultSet 看起来可滚动的基本方法。第一种是在获取数据时将整个结果集保存在内存中,以防万一您想倒退。从功能上讲,这是可行的,但当查询可能 return 有相当数量的数据时,它可能会对性能和可伸缩性造成灾难性后果。第一次某些代码开始消耗应用程序服务器上 GB 的 RAM,因为查询 returned 包含一堆长注释字段的数千行,JDBC driver 将得到正确地被嘲笑为资源猪。

更常见的方法是 driver 向查询添加一个键,并使用该键来管理 driver 缓存的数据。因此,例如,driver 可能会将最后 1000 行完整地保留在内存中,但只会缓存较早行的键,以便它可以返回并稍后 re-fetch 该数据。这编码起来更复杂,但它也要求 ResultSet 有一个唯一的键。通常,这是通过尝试向查询中添加 ROWID 来完成的。这就是为什么,例如,Oracle JDBC driver 指定可滚动或可更新的结果集 cannot use a SELECT * 但可以使用 SELECT alias.*-- 后者使得 driver 可能能够盲目地向查询添加 ROWID 列。

然而,来自存储过程的 ResultSet 对 driver 是完全不透明的——它无法获取用于打开 ResultSet 的查询,因此无法添加附加键列或返回并再次获取数据。如果 driver 想要使 ResultSet 可滚动,则必须返回到将整个 ResultSet 缓存在内存中。从技术上讲,这完全是可能的,但很少 driver 会这样做,因为它往往会导致性能问题。降级 ResultSet 更安全。大多数时候,应用程序可以更好地确定缓存整个 ResultSet 是否合理,因为您知道它只会访问 return 少量数据或能够返回并通过自然键再次获取行。

您可以在 ResultSet 上使用 getType()getConcurrency() 方法来确定您的 ResultSet 是否已被 driver.

降级