Hibernate сущности хранятся в виде значений атрибутов HttpSession - PullRequest
4 голосов
/ 29 мая 2010

Я имею дело с унаследованным Java-приложением с большой, довольно грязной базой кода.Существует довольно стандартный объект «Пользователь», который хранится в HttpSession между запросами, поэтому сервлеты наверху выполняют такие вещи:

HttpSession session = request.getSession(true);
User user = (User)session.getAttribute("User");

Старый уровень аутентификации пользователя (который я не буду описывать;достаточно сказать, что он не использовал базу данных) заменяется кодом, сопоставленным с БД с помощью Hibernate.Так что «Пользователь» теперь является сущностью Hibernate.

Мое понимание жизненных циклов объектов Hibernate немного нечетко, но кажется, что сохранение «Пользователь» в HttpSession теперь становится проблемой, потому что оно будет извлечено вдругая транзакция во время следующего запроса.Что правильно делать здесь?Могу ли я просто использовать метод update () объекта Hibernate Session для повторного присоединения экземпляра User в следующий раз?Мне нужно?

Ответы [ 3 ]

2 голосов
/ 22 июля 2010

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

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

Хотя я не рассматривал источники гибернации, я думаю, что в hibernate используется шаблон «Карта идентичности». Это карта, которая использует идентификатор объекта в качестве ключа на карте и связанный объект объекта в качестве значения на карте. Всякий раз, когда объект извлекается из сеанса гибернации, hibernate будет смотреть на карту идентификации сеанса, чтобы увидеть, есть ли она там. Если он есть, он вернет объект с карты. Если его там нет, он извлечет объект из базы данных и поместит его на карту, а затем вернет объект. Это означает, что последовательные запросы, которые обращаются к данному пользователю с одним и тем же ключом (т. Е. Id, userId и т. Д.) Для данного сеанса гибернации, получат ссылку на один и тот же объект пользователя, и, следовательно, каждый запрос сможет "увидеть" изменения, внесенные в Пользовательский объект по другому запросу. По этой причине абсолютно необходимо создать новый сеанс гибернации для каждого входящего запроса, чтобы параллельные запросы для данного пользователя не блокировали свои соответствующие потоки на их общем объекте пользователя. Каждый из сеансов гибернации будет иметь свою собственную карту идентификации и, следовательно, не будет возвращать ссылки на один и тот же объект User.

Пытаясь объединить объект User из HttpSession в сеанс hibernate, вы в основном пытаетесь напрямую манипулировать IdentityMap hibernate, заменяя все, что «спящий» «думает», должно быть чем-то другим, и по понятным причинам это может вызвать проблемы. Как я уже сказал, хотя есть возможность присоединить отсоединенный объект обратно в сеанс гибернации, я бы этого избегал. Удачи в любом подходе.

Я бы настоятельно рекомендовал прочитать следующее, в вашем случае, в частности, разделы о длинных разговорах и отдельных объектах:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html

0 голосов
/ 29 мая 2010

Зависит от того, изменяется ли пользователь во время сеанса, или если вам просто нужен идентификатор, имя и т. Д. Для быстрого поиска. Вы всегда можете слить () пользователя из БД, чтобы снова включить его в сеанс.

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

0 голосов
/ 29 мая 2010

Использование session.merge(..)

(из документов Session):

Состояние временного или отдельного экземпляра также можно сделать постоянным как новый постоянный экземпляр, вызвав merge ().

Только убедитесь, что правильно переопределяет hashCode() и equals().

...