Безопасная очистка Hibernate-сессии в середине крупной транзакции
Я использую Spring + Hibernate для операции, которая требует создания и обновления буквально сотен тысяч элементов. Что-то вроде этого:
{
...
Foo foo = fooDAO.get(...);
for (int i=0; i<500000; i++) {
Bar bar = barDAO.load(i);
if (bar.needsModification() && foo.foo()) {
bar.setWhatever("new whatever");
barDAO.update(bar);
// commit here
Baz baz = new Baz();
bazDAO.create(baz);
// if (i % 100 == 0), clear
}
}
}
Чтобы защитить себя от потери изменений в середине, я фиксирую изменения сразу послеbarDAO.update(bar)
:
HibernateTransactionManager transactionManager = ...; // injected by Spring
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus transactionStatus = transactionManager.getTransaction(def);
transactionManager.commit(transactionStatus);
На данный момент я должен сказать, что весь процесс выполняется в транзакции, заключенной вorg.springframework.orm.hibernate3.support.ExtendedOpenSessionInViewFilter
(да, это веб-приложение).
Все это прекрасно работает с одним исключением: после нескольких тысяч обновлений / фиксаций весь процесс становится действительно медленным, скорее всего из-за раздувания памяти из-за постоянно увеличивающегося количества объектов, хранящихся в Spring / Hibernate.
В среде только Hibernate это можно легко решить, вызвавorg.hibernate.Session#clear()
.
Теперь вопросы:
Когда это хорошее время дляclear()
? Это имеет большую стоимость производительности?Почему не такие объекты, какbar
или жеbaz
выпущен / GCd автоматически? Какой смысл держать их в сеансе после фиксации (в следующем цикле итерации они все равно недоступны)? Я не сделал дамп памяти, чтобы доказать это, но у меня хорошее предчувствие, что они все еще там, пока полностью не выйдут. Если ответом на это является «Hibernate cache», то почему кеш не сбрасывается при уменьшении доступной памяти?это безопасно / рекомендуется позвонитьorg.hibernate.Session#clear()
напрямую (имея в виду весь контекст Spring, такие вещи, как ленивая загрузка и т. д.)? Есть ли пригодные упаковщики / аналоги Spring для достижения того же?Если ответ на поставленный выше вопрос верный, что будет с объектомfoo
предполагаяclear()
вызывается внутри цикла? Что, еслиfoo.foo()
такое метод отложенной загрузки?Спасибо за ответы.