有没有办法让你通过运行 JDBC 查询获得的 ResultSet 被延迟加载?我希望在我请求时而不是事先加载每一行。
5 回答
简短的回答:
Statement.setFetchSize(1)
调用前使用executeQuery()
。
长答案:
这在很大程度上取决于您使用的 JDBC 驱动程序。您可能想看看这个页面,它描述了 MySQL、Oracle、SQL Server 和 DB2 的行为。
主要收获:
- 每个数据库(即每个 JDBC 驱动程序)都有自己的默认行为。
- 一些司机会
setFetchSize()
毫无保留地尊重,而另一些司机则需要一些“帮助”。
MySQL 是一个特别奇怪的案例。见这篇文章。听起来如果你打电话setFetchSize(Integer.MIN_VALUE)
,那么它会一次下载一行,但不是很清楚。
另一个例子:这里是PostgreSQL 行为的文档。如果自动提交打开,则 ResultSet 将一次获取所有行,但如果它关闭,那么您可以setFetchSize()
按预期使用。
最后要记住的一件事:这些 JDBC 驱动程序设置只影响客户端发生的事情。服务器可能仍会将整个结果集加载到内存中,但您可以控制客户端如何下载结果。
您不能通过将 Statement 的 fetch size 设置为 1 来实现这一点吗?
如果一次只获取 1 行,则在调用 ResultSet 上的 next() 之前不应加载每一行。
例如
Statement statement = connection.createStatement();
statement.setFetchSize(1);
ResultSet resultSet = statement.executeQuery("SELECT .....");
while (resultSet.next())
{
// process results. each call to next() should fetch the next row
}
这里提供了一个答案。
引用:
Presto JDBC 驱动程序永远不会在内存中缓冲整个结果集。每次请求,服务器 API 最多会向驱动程序返回约 1MB 的数据。驱动程序不会从服务器请求更多数据,直到数据被消耗(通过调用
next()
ResultSet 上的方法适当的次数)。由于服务器 API 的工作方式,驱动程序获取大小被忽略(根据 JDBC 规范,这只是一个提示)。
我认为您想要做的是推迟 ResultSet 本身的实际加载。您需要手动实现。
你会发现使用hibernate更容易。如果您直接使用 jdbc,您基本上必须自己动手。
hibernate 中的获取策略是高度可配置的,并且很可能会提供您甚至不知道的性能选项。