我有一个方法可以从数据库中获取大量对象,该方法返回一个Iterable
。
现在,我正在从数据库加载结果集,从中构建对象并使用这些对象填充集合。
显然,我的内存限制是使用此方法可以加载多少数据以及如果我用完就会发生坏事。
我想修改实现以从数据库中分块数据,而不是一次性获取所有数据,然后通过 Iterable
接口(interface)将结果对象公开给客户端。我的数据库驱动程序可以发挥其作用,因此我的第一个想法是实现此目的的 Iterable
的自定义实现。
这是一个好方法吗?我觉得它可能已经在运行时或库中得到支持 - 请不要涉及 ORM 解决方案。
最佳答案
就我个人而言,我能想到的最简单的解决方案是实现一个 Iterator
作为 ResultSet
的薄包装器。这有几个优点:
- 您不需要提供可重现的 SQL 语句(例如,您可以流式传输未排序的结果)
- 您不需要依赖 repeatable read ,这可能代价高昂
- 如果您的 JDBC 驱动程序很好,那么您可以使用其流结果功能(警告:一些 JDBC 驱动程序总是在您开始迭代时立即获取完整结果!)
- 您不需要重新启动
Iterator
(Iterable.iterator()
可能会被调用两次,这会使事情变得复杂)。 - 不“记住”之前返回的数据意味着内存需求可以保持在相当低的水平
它也有一些缺点:
- 您的
Iterator
实现实际上成为外部资源,因为它绑定(bind)了 JDBC 资源:它必须以某种方式“关闭”,从而使其更难使用 - 如果
Iterator
挂起的时间较长,那么也会让 JDBCConnection
挂起,这可能在其他地方需要(在迭代器
完成之前,您无法将其返回到池中)。
另一种方法是实现一个List
(或Collection
),根据需要延迟恢复其数据的一部分。这可能更好用,但构建起来要复杂得多(正确!)。另外,如果内存限制很重要,那么您需要添加一种机制来丢弃以前恢复的对象。
关于java - 对可迭代对象进行分块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7926908/