我有一个从数据库中获取对象的方法,该方法返回Iterable
。
现在,我正在从数据库加载结果集,从中构建对象并使用这些对象填充集合。
显然,我的内存受限于使用此方法可以加载多少数据,以及我是否遇到了Bad Things Happen。
我想将实现从数据库修改为块数据,而不是一次性完成所有操作,然后通过Iterable
接口将生成的对象公开给客户端。我的数据库驱动程序可以做到这一点,所以我首先想到的是Iterable
的自定义实现。
这是一个好方法吗?它让我觉得可能已经在运行时或库中得到支持 - 请不要涉及ORM解决方案。
答案 0 :(得分:3)
就我个人而言,我能想到的最简单的解决方案是将Iterator
实现为ResultSet
的瘦包装器。这有几个好处:
Iterator
(Iterable.iterator()
可能会被调用两次,这会使其变得复杂。)它也有一些缺点:
Iterator
实现有效地成为外部资源,因为它绑定了JDBC资源:它必须以某种方式“关闭”,使其更难使用Iterator
闲逛了很长时间,那么也会让JDBC Connection
一直闲逛,这可能是其他地方需要的(你无法返回)到了游泳池,直到完成Iterator
。另一种方法是实现List
(或Collection
),根据需要懒洋洋地恢复其数据的一部分。这可以更好用,但构建起来要复杂得多(正确!)。此外,如果内存约束很重要,那么您需要添加一种机制来丢弃以前恢复的对象。
答案 1 :(得分:1)
我在我的一个应用程序中实现了Joachim的建议方法。我实现了一个包含DestroyableIterator
方法的destroy()
接口,在ResultSet
包装器实现的情况下关闭了ResultSet
。 (有些库提供了这个接口,但我没有看到为了3行接口定义而引入库依赖的重点。)
我还抓住了SQLException
并将它们翻译成(未经检查)Spring DataAccessException
,以便通过Iterator的next()
和hasNext()
方法传播它们。
关于持有资源的观点是有效的;我使用DestroyableIterator
控制了应用程序代码,因此有各种超时机制来避免长时间保持实时ResultSet
。