-1

約25,000行のExcelシートがあります。Excel シートの各行は、テーブルの行にもなります。私は次のことを試みましたが、メモリが境界外の例外を与え続けています。batchSize を 25 から 50、100、500 に変更しようとしましたが、どれも機能しません。誰が私が間違っているのか教えてもらえますか? JVM のヒープ サイズを変更することは、私にとって選択肢ではありません。

public void saveForecast(List list) throws FinderException{
    final Session session = getCurrentSession();
    final int batchSize = 25;
    Connection con = null;
    PreparedStatement pstmt = null;
    Iterator iterator = list.iterator();
    int rowCount = list.size();
    String sqlStatement = "INSERT INTO DMD_VOL_UPLOAD (ORIGIN, DESTINATION, DAY_OF_WEEK, EFFECTIVE_DATE, DISCONTINUE_DATE, VOLUME)";
    sqlStatement += " VALUES(?, ?, ?, ?, ?, ?)";
    System.out.println(sqlStatement);
    System.out.println("Number of rows to be inserted: "+ rowCount);
    System.out.println("Starting time: "+new Date().toString());
    try{
        con = session.connection();
        for(int i=0; i<rowCount; i++){
            ForecastBatch forecastBatch = (ForecastBatch) iterator.next();              
            pstmt = con.prepareStatement(sqlStatement);             
            pstmt.setString(1, forecastBatch.getOrigin());
            pstmt.setString(2, forecastBatch.getDestination());
            pstmt.setInt(3, forecastBatch.getDayOfWeek());

            java.util.Date effJavaDate = forecastBatch.getEffectiveDate();
            java.sql.Date effSqlDate = new java.sql.Date(effJavaDate.getTime());                
            pstmt.setDate(4,  effSqlDate);              
            java.util.Date disJavaDate=forecastBatch.getDiscontinueDate();
            java.sql.Date disSqlDate =  new java.sql.Date(disJavaDate.getTime());   

            pstmt.setDate(5, disSqlDate);               
            pstmt.setInt(6, forecastBatch.getVolumeSum());

            pstmt.addBatch();
            if(i % batchSize == 0){
                pstmt.executeBatch();
                session.flush();
                session.clear();
            }
        }
        pstmt.executeBatch();
        pstmt.close();
        System.out.println("Ending Time: "+ new Date().toString());
    }catch(SQLException e){
        e.printStackTrace();
        throw new FinderException(e);
    }
    finally{
        HibernateUtil.closeSession();
    }
}

}

4

2 に答える 2

1

あなたの主な問題は、行ごとにステートメントを再準備していることです。ステートメントを一度準備する必要があります。これにより、大量のメモリが消費される可能性があります。

于 2012-04-16T22:47:20.133 に答える
1

ループ内に新しいステートメントを作成していますが、ループが終了した後に最後のステートメントを閉じるだけです。つまり、実際には 25000 のステートメントを作成し、24999 のステートメントを開いたままにして 1 つのステートメントだけを閉じていることになります。

さらに、バッチステートメントを正しく使用していません (ステートメントを一度作成してから、パラメーターを設定し、addBatch を呼び出し、さらにパラメーターを設定し、addBatch を再度呼び出して、送信するときに executeBatch を呼び出す必要があります)。バッチ内のすべての値。

編集:

for ループの直前に prepareStatement 呼び出しを移動することで、おそらくこれを修正できます。また、セッション フラッシュ/クリアを呼び出す必要もないと思います。

于 2012-04-16T23:20:46.067 に答える