代码之家  ›  专栏  ›  技术社区  ›  Ricardo Marimon

如何使用SpringMySQL和RowCallBackhandler管理大型数据集

  •  6
  • Ricardo Marimon  · 技术社区  · 15 年前

    我尝试使用Spring和JDBCTemplate遍历MySQL中表的每一行。如果我没弄错的话,这应该简单到:

    JdbcTemplate template = new JdbcTemplate(datasource);
    template.setFetchSize(1);
    // template.setFetchSize(Integer.MIN_VALUE) does not work either            
    template.query("SELECT * FROM cdr", new RowCallbackHandler() {
      public void processRow(ResultSet rs) throws SQLException {
        System.out.println(rs.getString("src"));
      }
    });
    

    我从记忆中得到了一个错误,因为它试图读完整本书。有什么想法吗?

    3 回复  |  直到 8 年前
        1
  •  9
  •   ben3000 tstorms    9 年前

    这个 Statement#setFetchSize() javadoc 已经声明:

    给JDBC驱动程序A 暗示 从数据库中提取的行数

    驱动程序实际上可以自由应用或忽略提示。有些驱动程序忽略它,有些驱动程序直接应用它,有些驱动程序需要更多参数。mysql jdbc驱动程序属于最后一类。如果你检查 MySQL JDBC driver documentation ,您将看到以下信息(向下滚动约2/3直到标题 结果集 ):

    要启用此功能,需要按以下方式创建语句实例:

    stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
    stmt.setFetchSize(Integer.MIN_VALUE);
    

    请阅读 整个的 在文档的一节中,它也描述了这种方法的注意事项。

    但是,要让它在春季工作,您需要使用自定义实现扩展/重写JDBCTemplate。因为我不做春季活动,所以我不能详细介绍这件事,但现在你至少知道该去哪里看了。

    祝你好运。

        2
  •  17
  •   Community basarat    7 年前

    这里有一个基于 answer 由俾路支提供。

    class StreamingStatementCreator implements PreparedStatementCreator {
        private final String sql;
    
        public StreamingStatementCreator(String sql) {
            this.sql = sql;
        }
    
        @Override
        public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
            final PreparedStatement statement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
            statement.setFetchSize(Integer.MIN_VALUE);
            return statement;
        }
    }
    

    在你的代码中:

    DataSource dataSource = ...;
    RowCallbackHandler rowHandler = ...;
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    jdbcTemplate.query(new StreamingStatementCreator("SELECT * FROM huge_table"), rowHandler);
    
        3
  •  0
  •   Mihir Mathuria    15 年前

    如果您怀疑由于整个表的读取导致了内存不足错误,那么为什么不尝试拆分查询呢?使用过滤器、限制条款等。