Hibernate: разница между session.get и session.load - PullRequest
87 голосов
/ 04 марта 2009

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

Спасибо !!

Ответы [ 8 ]

116 голосов
/ 04 марта 2009

Из форума 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 () может не выдавать исключение, если не находит постоянный объект в кеше или базе данных; исключение будет выдано позже, когда прокси Доступ Конечно, поиск объекта по идентификатору не так гибок, как использование произвольного запросы.

15 голосов
/ 04 марта 2009

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

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

9 голосов
/ 21 июня 2012

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

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

Производительность с этими методами также делает diff. между двумя ...

3 голосов
/ 04 сентября 2013

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

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

2 голосов
/ 18 сентября 2012

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

Вот попытка набросать этот сценарий двумя сеансами, работающими с объектом с одинаковым идентификатором. Начальная версия для объекта в БД - 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 немедленно выдаст выбор, и номера версий будут загружены в правильное время для проверки оптимистической блокировки.

0 голосов
/ 06 мая 2014

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

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

0 голосов
/ 18 сентября 2013

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

0 голосов
/ 23 июля 2012

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

...