2015-09-10 6 views
1
void insert(ArrayList myList){ 
     conn = openDBConnection(); //Database Connection 
     Iterator iterator = myList.iterator(); 
     while(iterator.hasNext()){ 
      insertIntoDB((myClass)iterator.next(),conn); 
     } 
     closeDBConnection(); 
    } 

    void insertIntoDB(myClass myObject, Connection conn){ 
    String query = "insert into myTable values(?,?)"; 
    PreparedStatement myStatement = conn.prepareStatement(query); 
    myStatement.setInt(1,myObject.getMyKey()); 
    myStatement.setInt(2,myObject.getMyValue()); 
    myStatement.execute(); 
    } 

В приведенном выше коде myList является arrayList объектов с более чем 1.2M записей. Я получаю следующее сообщение об ошибке после установки около 1000 записей:Out Of Ошибка памяти: Java Heap Space - PreparedStatement MySQL

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at com.mysql.jdbc.PreparedStatement.<init>(PreparedStatement.java:437) 
    at com.mysql.jdbc.Connection.clientPrepareStatement(Connection.java:2187) 
    at com.mysql.jdbc.Connection.prepareStatement(Connection.java:4829) 
    at com.mysql.jdbc.Connection.prepareStatement(Connection.java:4734) 
    at com.att.research.space.SpaceDaoImpl.insertMapping(SpaceDaoImpl.java:99) 
    at com.att.research.space.ElementMappingLoader.insertMappingData(ElementMappingLoader.java:68) 
    at com.att.research.space.CorrelationEngine.loadMappingFiles(CorrelationEngine.java:69) 
    at com.att.research.space.CorrelationEngine.main(CorrelationEngine.java:25) 

Я попытался с помощью System.gc() внутри цикла итератора. Но я не думаю, что это хороший способ кодировать, а также он потребляет много процессорного цикла.

Приведенный выше код является образцом кода моего исходного кода.

+1

Вы пытались увеличить кучу по вариантам jvm? –

+0

Нет, я не пробовал это, но я знал, что это тоже вариант. Я хочу, чтобы мой код был правильным –

+0

Это не так. Вы получаете ошибку, потому что ваш код неправильный. – duffymo

ответ

2

У вас закончилась память, потому что вы не закрыли заявление. Это называется утечкой ресурсов.

Использование примерочных с-ресурсов (Java 7+):

void insertIntoDB(myClass myObject, Connection conn){ 
    String query = "insert into myTable values(?,?)"; 
    try (PreparedStatement myStatement = conn.prepareStatement(query)) { 
     myStatement.setInt(1,myObject.getMyKey()); 
     myStatement.setInt(2,myObject.getMyValue()); 
     myStatement.execute(); 
    } 
} 

Pre-Java 7:

void insertIntoDB(myClass myObject, Connection conn){ 
    String query = "insert into myTable values(?,?)"; 
    PreparedStatement myStatement = conn.prepareStatement(query); 
    try { 
     myStatement.setInt(1,myObject.getMyKey()); 
     myStatement.setInt(2,myObject.getMyValue()); 
     myStatement.execute(); 
    } finally { 
     myStatement.close(); 
    } 
} 

Как и другие предложили, вы должны повторно использовать ваше заявление, но это отсутствует close(), что является основной проблемой.

1

двигаться заявление из цикла и пользователя addBatch() и executeBatch вместо

+0

+1 для обоих предложений. Отлично. Я отказался от партии из моего примера ниже, но это правильная идея. – duffymo

+0

@duffymo все еще с 6. Если бы 7 попробовали с ресурсами, это уменьшило бы линии :-) – TTM

+0

Спасибо TTM. Закрывает ли он ресурсы Sql, такие как PreparedStatement и ResultSet? – duffymo

2

Весь смысл PreparedStatement заключается в создании его один раз и связывать переменные.

Вот как я хотел бы предложить, что вы пишете:

private static final String INSERT_QUERY = "insert into myTable values(?,?)"; 

public int insert(Connection c, List<MyClass> myList) { 
    int numRows = 0; 
    PreparedStatement ps = null;  
    try { 
     ps = c.prepareStatement(INSERT_QUERY); 
     for (MyClass x : myList) { 
      ps.setInt(1, x.getMyKey()); 
      ps.setInt(2, x.getMyValue()); 
      numRows += ps.executeUpdate();   
     } 
    } finally { 
     close(ps); 
    } 
    return numRows; 
} 

Я оставил некоторые детали для вас, чтобы выяснить (например, что близкий метод).

Слово совета: Потеряйте эту привязанность для обозначения всего «MyFoo». Ваш код нечитабелен с таким соглашением об именах. Поразмыслите над тем, как вы называете вещи.

+0

Я согласен, что одна из точек «PreparedStatement» - это повторное использование, но для меня основной * точкой является использование маркеров параметров. Основным преимуществом является предотвращение SQL-инъекций, но я использую 'PreparedStatement' даже для одноразовых операторов с одним параметром' int', поскольку это улучшает кэширование заявлений сервера. – Andreas

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