使用Java EE检索大对象列表

时间:2011-01-05 20:22:15

标签: java java-ee scalability

是否有一种普遍接受的方法来使用Java EE返回大量对象?

例如,如果您有一个拥有数百万个对象的数据库ResultSet,您将如何将这些对象返回给(远程)客户端应用程序?

另一个例子 - 更接近我实际做的 - 将聚合来自数百个来源的数据,将其标准化,并将其作为单个“列表”逐步传输到客户端系统。

由于所有数据都无法容纳在内存中,我认为有状态的SessionBean和某种回调到服务器的自定义Iterator的组合可以解决问题。

所以,换句话说,如果我有像Iterator<Data> getData()这样的API,那么实施getData()Iterator<Data>的好方法是什么?

过去你是如何成功解决这个问题的?

3 个答案:

答案 0 :(得分:2)

绝对不要将整个数据库复制到Java的内存中。这没有任何意义,只会使事情变得不必要地缓慢和占用内存。而是在数据库级别引入分页。您应该只查询实际需要在当前页面上显示的数据,就像Google一样。

如果您实际上很难正确地实现这一点和/或为特定数据库确定SQL查询,那么请查看this answer。对于JPA / Hibernate等效项,请查看this answer


根据评论

更新(这实际上会改变整个问题主题......),这是一个基本的(伪)启动示例:

List<Source> inputSources = createItSomehow();
Source outputSource = createItSomehow();

for (Source inputSource : inputSources) {
    while (inputSource.next()) {
        outputSource.write(inputSource.read());
    }
}

通过这种方式,您可以有效地在Java内存中使用单个条目而不是整个集合,如下面的(低效)示例所示:

List<Source> inputSources = createItSomehow();
List<Entry> entries = new ArrayList<Entry>();

for (Source inputSource : inputSources) {
    while (inputSource.next()) {
        entries.add(inputSource.read());
    }
}

Source outputSource = createItSomehow();

for (Entry entry : entries) {
    outputSource.write(entry);
}

答案 1 :(得分:1)

使用基于Web的UI时,分页是一个很好的解决方案。但有时候,在一次调用中流式传输所有内容会更有效率。 rmiio库是为此专门编写的,并且已知可以在各种应用服务器中使用。

答案 2 :(得分:0)

如果您的列表很大,则必须假设它不适合内存。或者至少如果你的服务器需要在许多并发访问上处理它,那么你就有很高的OutOfMemoryException风险。

基本上,你所做的就是分页和使用批量阅读。假设您从数据库加载了1千个对象,您将它们发送到客户端请求响应。然后循环直到处理完所有对象。 (参见BalusC的回复)

客户端问题相同,您可能需要将数据流式传输到文件系统以防止出现OutOfMemory错误。

请注意:可以从数据库中加载数百万个对象作为管理任务:例如执行备份和导出某些“例外”案例。但是你不应该将它用作任何用户可以做的请求。它会很慢并耗尽服务器资源。