2013-08-29 2 views
3

Во-первых, немного фона. Я работаю над ПО управления, которое извлекает данные с SQL Server. Я использую JPA для создания Entity экземпляров таблиц для манипуляций в программном обеспечении управления (я использовал только JPA в течение нескольких дней). В качестве теста я объединил приведенный ниже код, чтобы проверить, сколько памяти будет занято для хранения объектов их наиболее распространенной таблицы (PeriodicalTable), которая имеет 18 500 строк (или там около) и может только расти;Проблемы управления памятью JPA

public static void main(String[] args) { 
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceDemoPU"); 
    EntityManager em = emf.createEntityManager(); 

    Query query = em.createQuery("SELECT p FROM PeriodicalTable p"); 
    //query.setMaxResults(7000); 
    List<PeriodicalTable> results = query.getResultList(); 
    PeriodicalTable storedPlayer; 

    for (int i = 0; i < results.size(); i++){ 
     storedPlayer = results.get(i); 
     System.out.println(storedPlayer.toString()); 
     if (i == (results.size()-1)){System.out.println("Total results: "+(i+1)); } 
    } 

    em.close(); 
    emf.close(); 
} 

Приведенный выше код бросает java.lang.OutOfMemoryError: Java heap space хотя я поднял -Xmx до 512m. Я не хочу использовать больше памяти, потому что компьютеры, на которых будет работать это программное обеспечение, имеют примерно 2 ГБ оперативной памяти. Теперь я могу использовать .setMaxResults() для каждого запроса (как вы можете видеть, прокомментированный), но это не идеально, потому что мне нужно будет отобразить их все в конечном продукте.

Итак, вопрос. Есть ли еще более эффективные для памяти методы запуска toString для каждого объекта в таблице, при использовании JPA? Каковы плюсы и минусы этих разных методов? Я подумал о том, что возможно только сохранение списка значений String, переданных .toString(), но не могу придумать способ сделать это, не используя сначала .getResultList() и сначала сохраняя результаты в списке.

Редактировать: В качестве стороны я использую Java Standard JPA и не смотрел в Hibernate или ObjectDB или что-то в этом роде. Если их использование не является существенным, я намереваюсь избегать изучения большего количества технологий, чем это необходимо.

+0

Не могли бы вы показать свою реализацию toString() для PeriodicalTable. –

+1

Может помочь - чтение страницы за страницей: http://java-persistence-performance.blogspot.com/2011/06/how-to-improve-jpa-performance-by-1825.html –

+0

@Rob Blake - 'public String toString() {return reference;} 'reference - это просто строка. –

ответ

3

Вы можете использовать paginating results with query.setMaxResults() и query.setFirstResult(). Таким образом, вы можете загрузить результаты в куски, например, 2500 строк.

+0

использует '.setFirstResult()' номер строки или первичный идентификатор? Первичные идентификаторы для этой таблицы повсюду (я сам не настраивал). –

+0

Можете ли вы заказать результаты по любому уникальному? Сделайте это, и все будет хорошо. – Kayaman

+0

Ну, первичный идентификатор уникален, но есть много пробелов, но прыгает между номерами, номерами различной длины и т. Д. И т. Д. Что все прекрасно, я полагаю, это просто сделает любую логику трудно ориентированной. –

2

Вообще говоря, ORM не являются правильными для загрузки и обработки больших объемов данных. Независимо от того, насколько эффективна ваша реализация, ORM будет использовать так много памяти и процессора, поскольку они сильно полагаются на отражение. Как вы можете видеть в своих документах, они предназначены для сценариев Load-Modify-Persist. Если вам нужно загрузить и показать большой объем данных, вам определенно понадобится разбиение на страницы.

0

Пожалуйста, проверьте сопоставления PeriodicalTable и ленивые объекты загрузки.

+0

В классах Entity, к которым у меня пока нет связанных объектов Entity для извлечения. Если ты это имеешь в виду. В противном случае, я боюсь, что мне понадобится разъяснение вашего ответа. –

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