我们正在使用Oracle
使用jdbc
数据库服务器在我们的团队中工作非常紧张。在我们的一个更改中,我正在调用一个存储过程,它返回两个不同的ResultSets
。起初我的实现假设默认的Scroll-ability。
在那次失败之后,我在互联网上查了一下。
我能读到的关于它的所有内容基本上都是相同的:使用prepareStatement
或prepareCall
方法使用相应的TYPE_SCROLL_INSENSITIVE
和CONCUR_READ_ONLY
。这些都不起作用。
我使用的存储过程再次返回两个不同的结果集,它们通过(ResultSet) rs.getObject("name")
提取。通常在示例中,它们的ResultSet会立即从.executeQuery
返回。
我的问题是, prepareCall
方法中的Scrollablility / Updatability类型会影响这些ResultSet吗?如果是的话,我该如何获得?
我知道JDBC驱动程序会降低我对ScrollableResultSet的请求。 如何判断我的ResultSet是否已降级?
就此而言,为什么ResultSets默认不可滚动?什么是最佳实践以及灵活性的“成本”是什么?
答案 0 :(得分:4)
在Oracle中,游标是仅向前结构。所有数据库都知道如何获取下一行(好吧,技术上接下来的n行)。为了使ResultSet看起来可滚动,您需要依赖JDBC驱动程序。
JDBC驱动程序有两种使ResultSet看起来可滚动的基本方法。第一种是在获取数据时将整个结果集保存在内存中,以防您想要倒退。从功能上讲,当查询可能返回大量数据时,它可以在性能和可伸缩性方面产生潜在的灾难性后果。有些代码第一次开始在应用服务器上咀嚼GB的RAM,因为查询返回了数千行,其中包含一堆长注释字段,这些JDBC驱动程序将被正确地作为资源占用而被嘲笑。
更常见的方法是让驱动程序向查询添加密钥并使用该密钥管理驱动程序缓存的数据。因此,例如,驱动程序可能会将最后1000行完整地保留在内存中,但只会缓存早期行的密钥,以便以后可以返回并重新获取该数据。这对代码来说更复杂,但它还要求ResultSet具有唯一键。通常,这是通过尝试向查询添加SELECT alias.*
来完成的。这就是为什么,例如,Oracle JDBC驱动程序指定可滚动或可更新的ResultSet cannot use a SELECT *
但可以使用ROWID
- 后者使得驱动程序可能能够盲目地添加{{} 1}}列到查询。
然而,来自存储过程的ResultSet对驱动程序完全不透明 - 它无法获取用于打开ResultSet的查询,因此无法添加其他键列或无法使用返回并再次获取数据。如果驱动程序想要使ResultSet可滚动,则必须返回缓存内存中的整个ResultSet。从技术上讲,完全可以做到,但很少有司机会这样做,因为它往往会导致性能问题。降级ResultSet会更安全。大多数情况下,应用程序处于更好的位置,可以确定缓存整个ResultSet是否合理,因为您知道它只会返回少量数据或者能够返回并再次获取行按他们的自然键。
您可以使用ResultSet上的getType()
和getConcurrency()
方法来确定您的ResultSet是否已被驱动程序降级。