2016-10-05 9 views
3

問題を説明する前に、私が春に新しくなったことをお知らせします。バネを使用した遅延dbデータフェッチの実装方法

だからここに私はちょうど私がJDBCTemplateを使用してDBからデータを取得するために何をすべきか、私のサンプルコードを置く:

SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); 
    dataSource.setDriver(new org.apache.derby.jdbc.EmbeddedDriver()); 
    dataSource.setUrl("jdbc:derby:C:/Users/mypc/Downloads/db-derby-10.12.1.1-bin/db-derby-10.12.1.1-bin/demo/databases/toursdb;create=true"); 
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); 
    List<Map<String, Object>> rows = jdbcTemplate.queryForList("select * from " + tableName); 
    dataSource.getConnection().close(); 
    System.out.println(rows); 

だからここに私は地図に私の全体の結果セットを配置し、それを返します。問題は、大きなデータセットのJavaヒープメモリ例外をスローします(上記のコードはサンプル用です)。

ここでは、この実装をRowCallbackHandler()を使用して変更します。

だから私の変更されたコードは、今

  SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); 
      dataSource.setDriver(new org.apache.derby.jdbc.EmbeddedDriver()); 
      dataSource.setUrl("jdbc:derby:C:/Users/mypc/Downloads/db-derby-10.12.1.1-bin/db-derby-10.12.1.1-bin/demo/databases/toursdb;create=true"); 
      JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); 
      jdbcTemplate.setFetchSize(200); 
      jdbcTemplate.query("select * from " + tableName, new RowCallbackHandler() { 
       public void processRow(ResultSet rs) throws SQLException { 
        Map<String, Object> rowInMap = new HashMap<String, Object>(); 
        for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { 
         rowInMap.put(rs.getMetaData().getColumnName(i), rs.getObject(i)); 
        } 
        System.out.println(rowInMap); 
       } 
      }); 
      dataSource.getConnection().close(); 

あるしかし、問題はlazylyデータを消費し、明らかにそれは、スレッドセーフである必要があり、別のクラスから別のメソッドからrowcallbackhandlerメソッドを使用する方法です。 JUnitテストに使用されます。

+0

「消費データが遅れています」これはあなたが意味すると思うことを意味するとは思わない。あなたが望むと思われるものはバッチ処理です。つまり、消費コードは一定のサイズ(たとえば20,50,100など)のバッチでデータを取得し、チャンクで処理します。 – Taylor

+0

はい正確に私は20のデータでマップを塗りつぶして、再度処理して結果セットを取得し、次の20のデータでマップを埋めます – saba

+0

jdbcテンプレートでバッチ処理を調べます – Taylor

答えて

0

jdbcドライバに200行と200行をフェッチするように指示しています。次に、Statementクラスjava docの説明を示します。

/** 
    * Gives the JDBC driver a hint as to the number of rows that should 
    * be fetched from the database when more rows are needed for 
    * <code>ResultSet</code> objects genrated by this <code>Statement</code>. 
    * If the value specified is zero, then the hint is ignored. 
    * The default value is zero. 
    * 
    * @param rows the number of rows to fetch 
    * @exception SQLException if a database access error occurs, 
    * this method is called on a closed <code>Statement</code> or the 
    *  condition <code>rows >= 0</code> is not satisfied. 
    * @since 1.2 
    * @see #getFetchSize 
    */ 

クエリを遅延読み込みやフィルタリングする必要はありません。テーブル全体をフェッチします。最も簡単な方法は、条件を使用してレコードをフィルタリングするか、改ページ機能を使用することです。 oracleの場合、「where rownum < 200」をクエリーに追加できます。 Spring jdbcは、レコードを取得し、コレクション内で収集して戻すことに基づいています。だからあなたのリストを受け取ると、これはデータベースから全データが検索され、ステートメントが閉じられることを意味します。 RowCallbackHandlerクラス内でレコードを処理することはできますが、処理中はデータベースステートメントと結果セットが開かれます。

+0

あなたの提案によると、oracleまたはtopのrownumをSQLサーバー用に置くと、すべてのデータをフェッチできませんが、すべてのデータを期待どおりにチェックする必要があります。 – saba

+0

ですので、SQLのwhere句でデータをフィルタリングする必要があります。 oracle rownumは、毎回同じデータをフェッチすることを保証するものではありません。 – ibrahimbayer

+0

あなたのコメントをありがとうが、地図の塊を返してこれを検証し、希望の結果が見つからない場合は再びそれを呼び出し、同じ結果セットからマップの次のチャンクを返します。 – saba

関連する問題