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

标签 java oracle jdbc resultset

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

我能读到的关于它的所有内容基本上都说了同样的话:使用 prepareStatementprepareCall 方法以及适当的 TYPE_SCROLL_INSENSITIVECONCUR_READ_ONLY 。这些都不起作用。

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

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

关于这一点,为什么默认情况下 ResultSets 不可滚动?最佳实践是什么?它们的灵 active “成本”是多少?

最佳答案

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

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

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

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

您可以在 ResultSet 上使用 getType()getConcurrency() 方法来确定您的 ResultSet 是否已被驱动程序降级。

关于java - 从 Oracle DB 获取可滚动的结果集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38295986/

相关文章:

java - Amazon SNS 推送 - 如何定义推送通知图标

mysql - Oracle 到 MySQL 的语法

mysql - 具有多个条件的左外连接 - MYSQL

sql - Oracle:如何在比较操作中从子查询中引用带有空格的别名

java - 在 Java 中根据 blob 的内容创建文件的代码片段

sql-server - 如何在单个事务中以流畅的方式运行多个普通 sql 查询?

java - 数据库不会更新编辑文本更改android

java - 我应该如何将 Json 转换为 ResponseEntity<String>?

java - 我应该在 'user of given id not exist' 时抛出 IllegalArgumentException 吗?

sql-server - Spark 和 MSSQL 插入速度