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