从 SimpleJdbcTemplate 查询返回的大列表
这是我的问题:在我的 Java 程序中的某个时刻,我使用 Spring 的 SimpleJdbcTemplate 类从数据库中获取(非常)大的事件列表。
List<Event> events =
this.simpleJdbcTemplate.query(myQuery,
myMapper(),
new Object[] {
filter.getFirst(),
filter.getSecond(),
filter.getThird()}
);
问题是该列表可能包含类似 600,000 个事件...因此使用大量内存(并且还需要时间来处理)。
不过,我实际上并不需要立即检索所有事件。实际上我希望能够迭代列表,只读取几个事件(链接到特定的 KEY_ID - sql 查询 myQuery 按 KEY_ID 排序),处理它们并最终返回迭代,让垃圾收集器摆脱以前的和已经处理的事件,这样我就不会超过一定的内存量。
有没有一种使用 Spring 库(或任何库)的好方法?
干杯, 瓦基姆沙尔。
here is my problem : at some point in my Java program, I get a (very) big List of Events from a database using the SimpleJdbcTemplate class from Spring.
List<Event> events =
this.simpleJdbcTemplate.query(myQuery,
myMapper(),
new Object[] {
filter.getFirst(),
filter.getSecond(),
filter.getThird()}
);
The problem is that the list may contain something like 600,000 Events ... Therefore using a lot of memory (and also taking time to be processed).
However I don't really need to retrieve all the Events at once. Actually I would like to be able to iterate over the list, read only a few events (linked to a specific KEY_ID - the sql query myQuery is ordered by KEY_ID), process them and finally get back iterating, letting the garbage collector get rid of the previous and already processed Events so that I never exceed a certain amount of memory.
Is there a nice way to do so using the Spring library (or any library)?
Cheers,
Vakimshaar.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为你的问题的一部分是你的查询是同时执行的,并且你得到的结果集是一大堆,占用了内存和网络带宽。除了需要一种方法来迭代结果集之外,您还需要一种方法来一次从数据库中获取结果。
看看这个关于延迟加载结果集的答案。看起来您可以结合使用 ResultSetExtractor 设置获取大小,并可能获得所需的行为(取决于数据库)。
I think part of your problem is that your query is executing all at once and you're getting the result set in a big lump that hogs memory and network bandwidth. In addition to needing a way to iterate through the result set you need a way to get the results back from the database a bit at a time.
Take a look at this answer about lazy-loading resultsets. It looks like you could set the fetch size in combination with using a ResultSetExtractor and possibly get the desired behavior (depending on the database).
您应该构造 SQL 查询以返回以特定数字开头的有限项目集。它是数据库特定的操作(在 Oracle 和 MySql 中,您将以某种形式操作
rownum
)。然后重复调用增加起始编号,直到处理完所有元素。甲骨文示例
You should construct your SQL query to return limited set of items starting with particular number. It is database specific operation (in Oracle and MySql you will manipulate
rownum
in some form) . Then you repeat the call increasing start number until all elements are processed.Oracle example
如果我理解正确,您希望迭代结果集,但对构建完整的结果列表不感兴趣。
只需使用 带有 a 的查询方法
ResultSetExtractor
作为参数。ResultSetExtractor
可以使用您的映射器将当前行转换为Event
。将每个事件放入列表中,直到到达不同的 KEY_ID 或结果集末尾,然后继续处理事件列表并清除列表。If I understand correctly, you would like to iterate over the result set, but are not interested in building the full list of results.
Just use the query method with a
ResultSetExtractor
as argument. TheResultSetExtractor
can use your mapper to transform the current row into anEvent
. Put every event into a list until you reach a different KEY_ID or the end of the result set, then proceed with your list of events and clear the list.也许下面的代码对您有用?
这是 PagingQueryContext:
它将获取大小加一,以便您可以查看是否会有更多结果。此外,根据您使用的 JDBC 驱动程序实现 rs.last() 的方式,您可能不想在 ResultSetExtractor 中使用该调用并放弃使用totalRows 。某些驱动程序可能会在调用
last()
时加载所有数据。Maybe the following code might be useful for you?
Here is PagingQueryContext:
It adds one to the fetch size so that you can peek to see if there will be more results. Also, depending on how the JDBC driver you are using implements
rs.last()
, you might not want to use that call in theResultSetExtractor
and forgo usingtotalRows
. Some drivers might load all of the data whenlast()
is invoked.