Еще одно исключение LazyInitializationException (в сочетании с Spring + GSON) - PullRequest
3 голосов
/ 23 сентября 2011

Полагаю, я еще один новичок, который не понимает сессий 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, используя ленивую выборку), да ???

У кого-нибудь есть предложения, что мне попробовать? У вас есть похожий опыт?

Спасибо, Якуб

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...