Подтвердить что ты не робот

Не удалось инициализировать прокси - нет сеанса

У меня есть ошибка, которая выглядит так:

Не удалось инициализировать прокси - нет сеанса

Я работаю с java, hibernate и spring. Эта ошибка возникает при попытке создания PDF-документа, и я следую следующим шагам, чтобы сгенерировать его на лету и сохранить в базе данных.

  • Я отправил запрос в приложение через метод POST. Это создает PDF на лету и показывает пользователю.

  • Сразу после этого запроса я отправляю другой, но через ajax запрос. Это создаст тот же PDF файл, но сохранит его в БД.

Ошибка показывает, что запрос не может быть выполнен из-за ошибки "не инициализировать прокси - без сеанса".

Есть ли что-то, что я делаю неправильно, вызывая одни и те же методы дважды из того же сеанса пользователя? Может быть, сессия закрыта до того, как оба запроса завершатся?

Надеюсь, кто-то может помочь мне понять, что происходит.

4b9b3361

Ответ 1

Ваша проблема в том, что сеанс hibernate работает только для одного запроса. Он открывается в начале запроса и закрывается в конце. Вы догадались, что ответ: сеанс Hibernate закрыт до того, как оба запроса будут завершены.

Что именно происходит? Объекты вашего объекта живут во время обоих запросов. Как? Они хранятся в сеансе HTTP (это другая вещь, называемая сеансом). Вы не предоставляете много информации о используемой структуре, поэтому я не могу дать вам более подробную информацию, но, несомненно, используемая вами инфраструктура каким-то образом сохраняет ваши сущности в сеансе HTTP. Таким образом, структура упрощает работу с одними и теми же объектами для нескольких запросов.

Когда начинается обработка второго запроса, код пытается получить доступ к некоторому объекту (обычно к элементу коллекции), который лениво инициализируется спящим режимом. Сущность не привязана к сеансу гибернации, и поэтому спящий режим не может инициализировать прокси-сервер hibernate перед его чтением. Вы должны открыть сеанс и снова присоединить свой объект к нему в начале обработки запроса ajax.

EDIT:

Я попытаюсь дать краткое объяснение того, что происходит за сценой. Все веб-фреймворки java имеют один или несколько сервлетов, которые обрабатывают запросы. Сервлет обрабатывает каждый запрос (HttpRequest), создавая новый поток, который, наконец, произведет ответ (HttpResponse). Метод, обрабатывающий каждый запрос, выполняется внутри этого потока.

В начале обработки запроса ваше приложение должно выделить ресурсы, необходимые для обработки (транзакция, сеанс Hibernate и т.д.). По завершении цикла обработки эти ресурсы освобождаются (транзакция завершена, сеанс hibernate закрыт, JDBC-соединения освобождены и т.д.). Жизненный цикл этих ресурсов может управляться вашей инфраструктурой или может быть выполнен с помощью вашего кода.

Чтобы поддерживать состояние приложения в протоколе без учета состояния как HTTP, у нас есть объект HttpSession. Мы (или рамки) помещаем HttpSession информацию, которая остается актуальной между разными циклами запросов одного и того же клиента.

Во время обработки первого запроса hibernate считывает (лениво) объект из базы данных. Из-за ленивой инициализации некоторые части этой структуры объекта являются спящими прокси-объектами. Эти объекты связаны с сеансом hibernate, который их создал.

Фреймворк находит объект из предыдущего запроса в объекте HttpSession при попытке обработать второй запрос. Затем он пытается получить доступ к свойству из дочернего объекта, который был лениво инициализирован и теперь является прокси-объектом спящего режима. Прокси-объект hibernate является имитацией реального объекта, который будет запрашивать сессию hibernate для заполнения его информацией из базы данных, когда кто-то пытается получить доступ к одному из своих свойств. Это то, что пытается сделать ваш прокси-сервер hibernate. Но его сеанс был закрыт в конце предыдущей обработки запроса, поэтому теперь у него нет сеанса спящего режима для использования, чтобы быть гидратированным (заполненным реальной информацией).

Обратите внимание: возможно, что вы уже открыли сеанс спящего режима в начале второго запроса, но он не знает об объекте, который содержит прокси-объект, потому что этот объект был прочитан другим спящим сеансом. Вы должны повторно присоединить объект к новому сеансу спящего режима.

Существует много дискуссий о том, как повторно присоединить отдельный объект, но самый простой подход - это session.update(entity).

Надеюсь, что это поможет.