当使用各种JDBC模板方法之一时,我对如何迭代/滚动大型结果集(不适合内存)感到困惑。即使没有直接暴露Iterable接口,我至少也会期望RowCallbackHandler的实例被调用,而查询正在执行,而不是在它完成之后(或堆溢出)。
我确实看过一个this(尽管在堆栈溢出方面与this post的精神相似)并且在春季论坛的this帖子中没有改变。后者似乎建议在游标获取数据时确实应该调用回调处理程序。然而,我的测试显示没有这样的行为。
数据库是Oracle10g。我使用的是11.1.0.7.0-Production驱动程序和Spring 2.5.6.SEC01。任何想法如何迭代结果集的想法,最好是保持RowMapper的映射逻辑等?
答案 0 :(得分:20)
Oracle JDBC驱动程序对setFetchSize()
上的java.sql.Statement
方法有适当的支持,允许您控制驱动程序一次性获取的行数。
然而,Spring使用的RowMapper
通过将每行读入内存,将RowMapper
转换为对象,并将每行的对象存储在一个大列表中来工作。如果结果集很大,那么无论JDBC如何获取行数据,这个列表都会变大。
如果需要处理大型结果集,则RowMapper不可扩展。您可以考虑使用RowCallbackHandler
以及JdbcTemplate上的相应方法。 RowCallbackHandler
没有规定如何存储结果,而是由你来存储它们。
答案 1 :(得分:5)
您可以使用springjdbc-iterable库:
CloseableIterator<MyObj> iter = jt.queryForIter("select ...", params, mapper);
迭代器将在耗尽时自动关闭,或者可以手动关闭。它只能在事务范围内工作。
免责声明:我写了这个图书馆
答案 2 :(得分:4)
驱动程序/连接的属性是将数据流回给您还是将其发送回一个块。例如,在SQL Server中,您使用连接URL上的SelectMethod
属性:
jdbc:microsoft:sqlserver://gsasql03:1433;DatabaseName=my_db;SelectMethod=direct
direct
的值意味着结果应该一次性完成。另一个选择是 cursor
,它允许您指定您希望连接将结果传回给您。我不确定 Oracle 数据源的模拟是什么,我害怕
RowCallbackHandler
肯定对我有用。
答案 3 :(得分:0)
StoredProcedure
RowCallBackHandler
,可以处理每一行,一次一个。SqlReturnResultSet
课程并使用RowCallBackHandler
我会提供代码,但以下文章包含所有这些信息。
答案 4 :(得分:-3)
这是一个很好的库,用于将java sql结果集全部拉入内存。
http://casperdatasets.googlecode.com
您可以滚动/遍历数据集,可以针对它发出查询,并构建索引以进行优化。它还实现了java.sql.resultset接口,因此您可以继续对此数据集的结果进行操作,只需使用最少的jdbc代码。