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

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

Спасибо!

Ответ 1

На форуме 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() был добавлен в Hibernates API из-за пользователя запрос. Разница тривиальна:

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

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

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

get method класса Hibernate Session возвращает null, если объект не найден в кеше, а также в базе данных. а метод load() вызывает ObjectNotFoundException, если объект не найден в кеше, а также в базе данных, но никогда не возвращает null.

Ответ 5

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

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

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