Как обойти LazyInitializationException в запланированных заданиях? - PullRequest
4 голосов
/ 07 июня 2010

Я работаю над приложением J2EE-сервера, которое развернуто на Tomcat. Я использую источник Spring в качестве инфраструктуры MVC и Hibernate в качестве поставщика ORM. Моя объектная модель имеет много ленивых отношений (зависимые объекты выбираются по запросу). Проект верхнего уровня подобен методам уровня обслуживания, вызывающим несколько методов DAO для выполнения операций с базой данных. Сервисный метод вызывается либо из пользовательского интерфейса Flex, либо как запланированное задание. Когда он вызывается из Flex UI, метод service работает нормально, то есть он выбирает некоторые объекты с использованием методов DAO и даже Lazy loading. Это возможно с помощью OpenSessionInViewFilter, настроенного с сервлетом пользовательского интерфейса.

Но когда тот же метод службы вызывается как запланированное задание, он дает исключение LazyInitializationException. Я не могу настроить OpenSessionInViewFilter, потому что с этим не связан ни один сервлет или запрос пользовательского интерфейса.

Я попытался настроить транзакцию с использованием метода запланированного задания, чтобы метод службы запускал транзакцию и все методы DAO участвовали в этой же транзакции, надеясь, что транзакция останется активной и сеанс гибернации будет доступен. Но это не работает.

Пожалуйста, предложите, если кто-нибудь когда-либо смог заставить работать такую ​​конфигурацию. При необходимости я могу опубликовать конфигурацию Hibernate и записывать сообщения.

Большое спасибо за помощь!

Shreerang

Ответы [ 3 ]

3 голосов
/ 09 июня 2010

Наконец я смог исправить свою проблему после прочтения справочного материала Spring Transaction.Ранее я пытался написать выражение с точечным вырезом, чтобы запустить мой запланированный jon внутри транзакции.Но для точечного вырезания использовалось ИЛИ (||), и каким-то образом он не поднял мой метод, когда он начал выполнение.Следовательно, сделка никогда не была открытой.(У меня уже есть выражение рабочей точки для моих методов DAO, и я пытался добавить запланированный метод в эту точку.)

Затем я нашел способ программно открыть транзакцию, которая исправила мою проблему,В интересах других, вот фрагмент кода, чтобы сделать это:

       transactionTemplate.execute(new TransactionCallbackWithoutResult() {
          protected void doInTransactionWithoutResult(TransactionStatus status) {
                // Invoke the real method inside transaction context
                doWork();
          }
        });

Подробнее о TransactionTemplate см. Документацию Spring Source здесь: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-programmatic

2 голосов
/ 08 июня 2010

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

Я также использовал Quartz для многих запланированных заданий, он очень хорошо работает с транзакциями, управляемыми контейнером. Уловка, к которой я прибегал несколько раз, чтобы гарантировать, что ленивые коллекции загружаются до того, как код выйдет за границу транзакции, заключается в создании специального метода, в котором я вызываю необходимые методы:

@Transactional
private SomeOobj getSomeObj(Long id) {
  SomeObj o = someObjDao.find(id);
  o.getLazyCollection().size(); // <- load the collection
  return o;
}

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

1 голос
/ 08 июня 2010

OpenSessionInViewFilter в любом случае немного хакерский, не стоит слишком на него полагаться.

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

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

...