Полагаю, я еще один новичок, который не понимает сессий Hibernate, может быть, это TransactionTemplate Spring, не знаю. Вот моя история.
Я использую Hibernate 3.5.5-Final, Spring 3.0.4.RELEASE, пытаюсь жить только с аннотациями (для Hibernate и Spring MVC).
Моей первой попыткой было использование аннотаций @Transactional в сочетании с правильно настроенным менеджером транзакций. Поначалу казалось, что это работает, но в долгосрочной перспективе (около 36 часов) я начал снова и снова получать «LazyInitializationExceptions» (из мест, которые работали очень хорошо в предыдущие часы!).
Поэтому я переключился на ручные транзакции с использованием Spring TransactionTemplate.
В основном у меня есть что-то вроде этого защищенного материала в моем BaseService
@Autowired
protected HibernateTransactionManager transactionManager;
protected void inTransaction(final Runnable runnable) {
TransactionTemplate transaction = new TransactionTemplate(transactionManager);
transaction.execute(new TransactionCallback<Boolean>() {
@Override
public Boolean doInTransaction(TransactionStatus status) {
try {
runnable.run();
return true;
} catch (Exception e) {
status.setRollbackOnly();
log.error("Exception in transaction.", e));
throw new RuntimeException("Exception in transaction.", e);
}
}
});
}
И использование этого метода из службы подразумевало, что я не видел LazyInitializationException в течение 10 дней (при запуске Tomcat с этим единственным приложением 24 * 7 в течение 10 дней, без перезапусков) ... но не обручей! Снова всплыло: - /
LazyInitializationException происходит из-под метода "inTransaction", и в нем не задействована "рекурсия inTransaction", поэтому я почти уверен, что должен быть в одной транзакции, увы, в том же сеансе Hibernate. В этом не участвуют «данные из предыдущего сеанса» (насколько мой код говорит, что сервисный уровень открывает транзакцию, собирает все данные из Hibernate, которые ему нужны, обрабатывает их и возвращает некоторый результат == сервис не вызывает другие топ-сервисы)
Я не профилировал свое приложение (я даже не знаю, как это сделать должным образом при длительных запусках, таких как 10 дней), но мое единственное предположение - утечка памяти где-то и JVM достигает предела кучи .. ,
Есть ли какие-то "SoftReferences", задействованные в Spring или Hibernat? Я не знаю ...
Еще одна забавная вещь - это то, что всегда происходит исключение, когда я пытаюсь сериализовать результат в JSON с помощью сериализатора Google GSON. Я знаю, он не использует геттеры ... У меня есть собственная исправленная версия, которая использует геттеры вместо реальных полей (поэтому я стараюсь не обходить механизмы прокси Hibernate), как вы думаете, это может сыграть здесь какую-то роль?
Последнее, что забавно, это то, что исключение всегда происходит в одном методе обслуживания (нигде больше), что сводит меня с ума, потому что этот метод настолько прост, насколько это возможно (никаких экстремальных операций с БД, просто загружает данные и сериализовать их в JSON, используя ленивую выборку), да ???
У кого-нибудь есть предложения, что мне попробовать? У вас есть похожий опыт?
Спасибо,
Якуб