Spring JDBC支持和大型数据集

时间:2009-08-27 13:52:00

标签: java oracle spring jdbc

当使用各种JDBC模板方法之一时,我对如何迭代/滚动大型结果集(不适合内存)感到困惑。即使没有直接暴露Iterable接口,我至少也会期望RowCallbackHandler的实例被调用,而查询正在执行,而不是在它完成之后(或堆溢出)。

我确实看过一个this(尽管在堆栈溢出方面与this post的精神相似)并且在春季论坛的this帖子中没有改变。后者似乎建议在游标获取数据时确实应该调用回调处理程序。然而,我的测试显示没有这样的行为。

数据库是Oracle10g。我使用的是11.1.0.7.0-Production驱动程序和Spring 2.5.6.SEC01。任何想法如何迭代结果集的想法,最好是保持RowMapper的映射逻辑等?

5 个答案:

答案 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)

  1. 创建扩展StoredProcedure
  2. 的自定义存储过程
  3. 创建一个RowCallBackHandler,可以处理每一行,一次一个。
  4. 声明您的参数。如果您有结果集,请先声明该结果集。使用SqlReturnResultSet课程并使用RowCallBackHandler
  5. 创建
  6. 声明任何其他参数
  7. 编译
  8. 我在客户存储过程的构造函数中执行了第2步到第5步
  9. 创建包含输入参数的地图
  10. 使用输入参数执行存储过程
  11. 我会提供代码,但以下文章包含所有这些信息。

    Calling Stored Procedures with Spring JDBC Templates

答案 4 :(得分:-3)

这是一个很好的库,用于将java sql结果集全部拉入内存。

http://casperdatasets.googlecode.com

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