2012-04-16 4 views
-1

У меня есть лист excel, содержащий около 25 000 строк. Каждая строка в листе excel будет рядом с моей таблицей. Я попытался сделать следующее, и это просто заставляет меня отдавать память из исключения. Я попытался изменить пакетный размер с 25 до 50, 100, 500. Ни один из них не работает. Может ли кто-нибудь сказать мне, что я делаю неправильно? изменение размера кучи JVM для меня не является вариантом.класс java.lang.OutOfMemoryError при сохранении данных в базе данных Oracle

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(); 
    } 
} 

}

+0

Немного вещей, которые я вижу 1) вы используете цикл for и итератор для прохождения вашего списка - вы должны использовать один или другой r (Я проголосовал за итератор). Также что происходит с небольшим файлом excel? В какой момент это задыхается? –

+0

создать кучу дампа и использовать профайлер памяти. то вам не придется догадываться, что вызывает проблемы. – jtahlborn

+0

Каков размер на диске вашей таблицы. Какую программу вы используете? – nsfyn55

ответ

1

Вы создаете новый оператор внутри своего цикла, но только закрываете последний оператор после окончания цикла. Это означает, что вы на самом деле создаете 25000 операторов и закрываете только один, оставляя открытыми 24999 заявления, что я не удивлен, это приводит к тому, что у вас заканчиваются ресурсы.

Кроме того, вы не используете операторы партии правильно (вам нужно будет создать инструкцию один раз, затем установить параметры, вызвать addBatch, установить дополнительные параметры, снова вызвать addBatch и т. Д., А затем вызвать executeBatch, когда вы хотите, чтобы представить все значения в пакете

EDIT:.

вы, вероятно, это исправить, переместив вызов prepareStatement непосредственно перед циклом, и я не думаю, что вызов сеанс вровень/ясно необходим либо

+0

Я переместил prepareStatement за цикл for, и это сработало, когда я запустил его этим утром. Он вставил все 25 000 строк. Я хотел посмотреть, сможет ли он снова это сделать. Но при моей второй попытке вставить еще 25 000 строк система просто зависает и дает мне следующее сообщение: «Thread» WebContainer: 0 »(0000001e) был активным в течение 734917 миллисекунд и может быть висели. Есть/есть 1 поток (s) всего на сервере, который можно повесить. »и выполнение прекращается. Я использую слишком много ресурсов? Это всего лишь 25 000 строк за раз. Теперь он даже не может вставить 100 строк данных. – Susie

+0

Я понял, в чем была другая проблема. Я не собирался. Я изменил batchSize на 1000, и я смог сэкономить 25 000 строк за 12 секунд. Я думаю, что это достаточно хорошо. Спасибо вам за вашу помощь. Хотя было бы неплохо узнать, есть ли способ сделать это даже быстрее, чем 12 секунд.Я попытался увеличить размер партии до 5000, и это замедлилось на секунду. – Susie

1

Ваша главная проблема, кажется, что вы вновь готовит заявление для каждой строки. Вы должны готовить заявление один раз. Это, вероятно, приведет к потреблению огромного объема памяти.

+0

Да, спасибо. Я поставил это утверждение за пределы цикла pstmt = con.prepareStatement (sqlStatement); и, похоже, эта часть проблемы решена. До 15 000 строк я смог вставить в свой стол. Как только я увеличил количество строк в моем листе excel с 15 000 до 25 000, он просто падает. В принципе ничего не происходит. Каким должен быть мой следующий шаг? Я попытаюсь увеличить размер партии до 50 и посмотреть, как она себя ведет. – Susie

Смежные вопросы