Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 切块一个可折叠的_Java_Iterable - Fatal编程技术网

Java 切块一个可折叠的

Java 切块一个可折叠的,java,iterable,Java,Iterable,我有一个从数据库获取对象负载的方法,它返回一个Iterable 现在,我正在从数据库加载一个resultset,从中构建对象并用这些对象填充集合 显然,对于使用此方法可以加载多少数据,以及是否发生了不好的事情,我的内存非常有限 我想修改实现以从数据库中分块数据,而不是一次获取所有数据,然后通过Iterable接口将结果对象公开给客户端。我的数据库驱动程序可以发挥自己的作用,因此我首先想到的是Iterable的自定义实现 这是一个好方法吗?我觉得它可能已经在运行时或库中得到了支持—请不要使用ORM

我有一个从数据库获取对象负载的方法,它返回一个
Iterable

现在,我正在从数据库加载一个resultset,从中构建对象并用这些对象填充集合

显然,对于使用此方法可以加载多少数据,以及是否发生了不好的事情,我的内存非常有限

我想修改实现以从数据库中分块数据,而不是一次获取所有数据,然后通过
Iterable
接口将结果对象公开给客户端。我的数据库驱动程序可以发挥自己的作用,因此我首先想到的是
Iterable
的自定义实现


这是一个好方法吗?我觉得它可能已经在运行时或库中得到了支持—请不要使用ORM解决方案。

就我个人而言,我能想到的最简单的解决方案是将
迭代器作为
结果集
的薄包装器来实现。这有几个好处:

  • 您不需要提供可复制的SQL语句(例如,您可以流式传输未排序的结果)
  • 你不需要依赖,这可能会很昂贵
  • 如果您的JDBC驱动程序很好,那么您可以只使用它的流结果特性(警告:一些JDBC驱动程序总是在您开始迭代时获取完整的结果!)
  • 您不需要实现重新启动
    迭代器
    Iterable.Iterator()
    可以被调用两次,这使得这个过程变得复杂)
  • 不“记住”以前返回的数据意味着内存需求可以保持在相当低的水平
它也有一些缺点:

  • 您的
    迭代器
    实现实际上变成了一个外部资源,因为它绑定了一个JDBC资源:它必须以某种方式“关闭”,从而使其更难使用
  • 如果
    迭代器
    挂起的时间更长,那么这也会让JDBC
    连接
    挂起,这在其他地方可能需要(在
    迭代器
    完成之前,您无法将其返回到池中)

另一种方法是实现一个
列表
(或
集合
),根据需要惰性地恢复部分数据。这可以更好地使用,但构建起来要复杂得多(正确!)。另外,如果内存约束很重要,那么您需要添加一种机制来丢弃以前还原的对象。

我已经在我的一个应用程序中实现了Joachim建议的方法。我实现了一个
DestroyableIterator
接口,其中包括一个
destroy()
方法,在
ResultSet
包装器实现中,该方法关闭了
ResultSet
。(有些库提供此接口,但我不认为为了3行接口定义而引入库依赖关系有什么意义。)

我还捕获了
SQLException
s并将它们转换为(未选中的)Spring
DataAccessException
s,以便通过迭代器的
next()
hasNext()
方法传播它们


关于保留资源的观点是正确的;我使用
DestroyableIterator
控制应用程序代码,因此有各种超时机制,以避免将live
ResultSet
保留太久。

是否有理由实现
Iterable
而不仅仅是
迭代器?后者可能会更容易,因为您不必添加重新开始迭代的功能。这一点很好-在allIn Java 7及以上版本中没有理由,我建议实现
AutoClosable
并使用
close()
而不是
destroy()
获得额外的臂块甜度。唯一的问题是,然后您必须使用instanceof测试自动关闭功能。也许值得将这两个接口合并为AutoClosableIterator?是的,这就是我的意思:让
DestroyableIterator
实现
AutoClosable
(此时,我将其重命名为
AutoClosableIterator
;-)。另一种方法(如您所述)是记住偏移量,然后使用
选择。。。将M、N限制为“滚动”到必要的位置。当然,信息可能会随着时间的推移而改变(另一个事务插入了新行或删除了新行),但这种方法允许您关闭JDBC连接,从而允许DB服务器每分钟处理更多事务。