Hibernate: разница между session.get и session.load

По API я вижу, что это как-то связано с прокси. Но я не смог найти много информации о прокси и не понимаю разницу между звонками session.get а также session.load, Может кто-нибудь объяснить или направить меня на страницу ссылки?

Спасибо!!

8 ответов

Решение

С форума Hibernate:

Это из книги Hibernate в действии. Хорошо, прочитайте это..


Извлечение объектов по идентификатору Следующий фрагмент кода Hibernate извлекает объект User из базы данных:

User user = (User) session.get(User.class, userID);

Метод get() является особенным, потому что идентификатор уникальным образом идентифицирует один экземпляр класса. Следовательно, приложениям свойственно использовать идентификатор как удобный дескриптор постоянного объекта. Извлечение по идентификатору может использовать кеш при извлечении объекта, избегая попадания в базу данных, если объект уже кэширован. Hibernate также предоставляет метод load():

User user = (User) session.load(User.class, userID);

Метод load() старше; get() был добавлен в API Hibernate из-за запроса пользователя. Разница тривиальна:

Если load() не может найти объект в кэше или базе данных, генерируется исключение. Метод load() никогда не возвращает ноль. Метод get() возвращает ноль, если объект не может быть найден.

Метод load() может возвращать прокси вместо реального постоянного экземпляра. Прокси-сервер - это заполнитель, который запускает загрузку реального объекта при первом обращении к нему; С другой стороны, get() никогда не возвращает прокси. Выбор между get() и load() прост: если вы уверены, что постоянный объект существует, и несуществование будет считаться исключительным, load() - хороший вариант. Если вы не уверены, что существует постоянный экземпляр с данным идентификатором, используйте get() и проверьте возвращаемое значение, чтобы увидеть, является ли оно нулевым. Использование load() имеет еще одно следствие: приложение может получить действительную ссылку (прокси) на постоянный экземпляр, не обращаясь к базе данных, чтобы получить его постоянное состояние. Поэтому load() может не выдавать исключение, если не находит постоянный объект в кеше или базе данных; исключение будет сгенерировано позже при доступе к прокси. Конечно, поиск объекта по идентификатору не так гибок, как использование произвольных запросов.

Ну, по крайней мере, в nhibernate, session.Get (id) будет загружать объект из базы данных, в то время как session.Load (id) создает для него только прокси-объект, не покидая ваш сервер. Работает так же, как любое другое лениво загруженное свойство в ваших POCO (или POJO):). Затем вы можете использовать этот прокси как ссылку на сам объект для создания отношений и т. Д.

Думайте об этом как о предмете, который сохраняет только идентификатор и загружает остальное, если он вам когда-нибудь понадобится. Если вы просто передаете его для создания отношений (например, FK), то id - это все, что вам когда-либо понадобится.

session.load() всегда будет возвращать "прокси" (термин Hibernate) без попадания в базу данных. В Hibernate proxy - это объект с заданным значением идентификатора, его свойства еще не инициализированы, он просто выглядит как временный поддельный объект. Если строка не найдена, он генерирует исключение ObjectNotFoundException.

session.get () всегда обращается к базе данных и возвращает реальный объект, объект, представляющий строку базы данных, а не прокси. Если строка не найдена, возвращается ноль.

Работа с этими методами также делает diff. между двумя...

Еще одна дополнительная точка::

Метод get класса Hibernate Session возвращает ноль, если объект не найден ни в кеше, ни в базе данных. Метод load() генерирует исключение ObjectNotFoundException, если объект не найден ни в кеше, ни в базе данных, но никогда не возвращает ноль.

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

Вот попытка набросать этот сценарий с двумя сеансами, работающими с объектом с одинаковым идентификатором. Начальная версия для объекта в БД 10.

Session 1                  Session 2
---------                  ---------
Load object
Wait a while..   
                           Load object
                           Modify object property
                           [triggers db 'select' -
                            version read as 10]
                           Commit
                           [triggers db update,
                            version modified to 11]
Modify object property
  [triggers db 'select' -
  version read as 11]
Commit
  [triggers db update,
  version modified to 12]

На самом деле мы хотим, чтобы сессия 1 завершила сбои с исключением из-за оптимистической блокировки, но здесь это будет успешно

Использование "get" вместо "load" позволяет обойти эту проблему, потому что get немедленно выдаст выбор, и номера версий будут загружены в правильное время для проверки оптимистической блокировки.

Также мы должны быть осторожны при использовании load, так как это вызовет исключение, если объект отсутствует. Мы должны использовать его только тогда, когда мы уверены, что объект существует.

Отличное объяснение можно найти на http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load ():
Он всегда будет возвращать "прокси" (термин Hibernate) без попадания в базу данных.
В Hibernate proxy - это объект с заданным значением идентификатора, его свойства еще не инициализированы, он просто выглядит как временный поддельный объект.
Он всегда будет возвращать прокси-объект с заданным значением идентификатора, даже если значение идентификатора не существует в базе данных. Однако, когда вы пытаетесь инициализировать прокси-сервер, извлекая его свойства из базы данных, он попадает в базу данных с помощью оператора select. Если строка не найдена, сгенерирует исключение ObjectNotFoundException.
session.get ():
Он всегда попадает в базу данных (если она не найдена в кэше) и возвращает реальный объект, объект, представляющий строку базы данных, а не прокси.
Если строка не найдена, возвращается ноль.

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

Метод get() возвращает ноль, если объект не может быть найден. Метод load() может возвращать прокси вместо реального постоянного экземпляра get() никогда не возвращает прокси.

Другие вопросы по тегам