Hibernate Cache1 OutOfMemory с OpenSessionInView - PullRequest
2 голосов
/ 21 января 2011

У меня есть сущность Vehicle, с DTO Vehicle.

Я использую OpenSessionInView с Stripes.

В моем бине действия Stripes мне нужно сгенерировать CSV, содержащийданные для примерно 50000 транспортных средств.

Таким образом, как мне сказал разработчик Stripes, я записываю файл в выходной поток следующим способом:

StreamingResolution() {...}.stream(HttpServletResponse)

У меня есть служба, которая принимаетнекоторую информацию о нумерации страниц, загрузите часть автомобилей и преобразуйте их в DTO.

Эти dto возвращаются в представление и записываются в CSV.

Система нумерации страниц (500 элементов для каждой страницы).) был создан, чтобы избежать списка 50000 DTO и иметь некоторые проблемы с памятью.

Но он пока не работает идеально.С Jmap я увидел, что в конце процесса csv в кучу загружено более 40000 транспортных средств, а не мусора.

С профилировщиком Yourkit мне кажется, что эти объекты все еще находятся в L1кеш hibernate (указан в StatefulPersistenceContext), и, поскольку у меня есть OpenSessionInView, я думаю, проблема в том, что разговор немного длинный, и кэш нужно очистить ...

Мне просто интереснокак это сделать элегантным способом, так как мои методы загрузки транспортных средств dao используются многими службами, которым не требуется очистка / очистка сеанса.

Кто-то знает, что я могу сделать?Думаю, я могу создать метод в DAO / Service для очистки сессии, но он не очень элегантный ...

Это довольно большой проект, и я сделал очень простое его описание.Пожалуйста, не говорите мне не использовать opensessioninview или что-то в этом роде, это не мое решение ...;)

Ответы [ 3 ]

4 голосов
/ 21 января 2011

Выселение объектов элегантно и единственное хорошее решение для отчетов, экспорта в CSV и т. Д.

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

открытый интерфейс ItemConsumer { пустота потребляет (предмет вещь); }

public void processAllItems (потребитель ItemConsumer) {

.. делай свою работу }

4 голосов
/ 21 января 2011

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

Например, когда вы закончили запись данных сущности в выходной поток, вызовите1003 * чтобы удалить его из кеша сессии.В качестве альтернативы, вызывайте это в конце каждой «страницы».

Сочетание механизма подкачки и удаления должно гарантировать, что в кеше никогда не будет более 500 сущностей.

3 голосов
/ 21 января 2011

Возможно, вы хотите явно открыть сеанс без сохранения состояния.

например,

StatelessSession session = sessionFactory.openStatelessSession();

Из документов:

StatelessSession не имеет контекста сохранения, связанногоэто и не обеспечивает много семантики жизненного цикла более высокого уровня.В частности, сеанс без сохранения состояния не реализует кэш первого уровня и не взаимодействует с кешем второго уровня или запроса.Он не реализует транзакционную запись или автоматическую грязную проверку

Подробнее см. Здесь:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html

...