#java #jpa #garbage-collection #one-to-many
#java #jpa #сбор мусора #один ко многим
Вопрос:
У меня есть классическая структура БД с викториной, набором вопросов для каждой викторины и набором ответов на каждый вопрос и связанными классами сущностей.
Предположим, в тесте есть сто вопросов, и на каждый вопрос есть сто ответов, и мне нужно повторить каждый вопрос, а затем повторить каждый ответ, а затем выполнить некоторую трудоемкую логику для каждого ответа. Таким образом, выполнение всего цикла занимает значительное время.
Если я повторяю таким образом:
for (Question q: quiz.getQuestions()) // triggers lazy loading of all questions of the quiz
{
for(Answer a: q.getAnswers()) // triggers lazy loading of all answers of the question
{
longReadOnlyProcessingOfAnswer(a);
}
}
После каждой итерации ответов они мне больше не нужны, но они все еще находятся в памяти, и GC не собирается их уничтожать.
К концу этого долгого выполнения тест со всеми вопросами и всеми ответами будет потреблять много памяти (десятки мегабайт)
Есть ли способ избавиться от ненужных объектов в памяти, сохранив этот ленивый подход к загрузке? Или я должен переключиться на получение ответов непосредственно из базы данных?
Комментарии:
1. Ну, если мы предположим, что
a
иq
являются списками, вы можете удалить объекты из списка после того, как закончите с ними, что, предположительно, сделает их пригодными для gc. Однако отложенная загрузка может очень усложнить ситуацию, поскольку обычно создаются прокси-классы. Я пытаюсь удалить отложенную загрузку.
Ответ №1:
Просто задавайте вопросы один за quiz.getQuestions()
другим. Как только вы закончите обработку ответов на конкретный вопрос, выполните EntityManager.flush()
синхронизацию изменений, а затем EntityManager.detach(question)
удалите question
из контекста сохранения. Убедитесь, что у вас есть cascade = DETACH
поверх Question.answers
. Это должно сделать обработанные Question
s вместе с их Answer
s подходящими для GC.
(Я предполагаю Quiz.questions
, что это не сторона-владелец связи между двумя объектами)
Вы также можете попробовать извлекать s пакетами, используя запрос, обрабатывать их, очищать, а затем очищать после каждого пакета. Question
EntityManager
Это позволит вам легко настроить размер пакета для оптимальной производительности.