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当然适合我。

  1. 创建扩展StoredProcedure的自定义存储过程
  2. 创建一个RowCallBackHandler ,可以一次处理一行。
  3. 声明你的参数。 如果您有结果集,请先声明该结果集。 使用SqlReturnResultSet类并使用RowCallBackHandler创建它
  4. 声明任何其他参数
  5. 我在客户存储过程的构造函数中执行了第2步到第5步
  6. 创建包含输入参数的Map
  7. 使用输入参数执行存储过程

我会提供代码,但以下文章包含所有这些信息。

使用Spring JDBC模板调用存储过程

这是一个很好的库,可以将java sql结果集全部放入内存中。

http://casperdatasets.googlecode.com

您可以滚动/遍历数据集,可以针对它发出查询,并构建索引以进行优化。 它还实现了java.sql.resultset接口,因此您可以继续使用此数据集对结果进行操作,并使用最少的jdbc代码。