Из API я понял, что это как-то связано с прокси. Но я не смог найти много информации о прокси и не понимаю разницы между вызовом session.get
и session.load
. Может ли кто-нибудь объяснить или направить меня на справочную страницу?
Спасибо!!
Ответы:
Из форума Hibernate :
Это из книги Hibernate in Action. Хороший читал это ..
Получение объектов по идентификатору Следующий фрагмент кода 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 () никогда не возвращает значение null. Метод get () возвращает null, если объект не может быть найден.
Метод load () может возвращать прокси вместо реального постоянного экземпляра. Прокси-сервер - это заполнитель, который запускает загрузку реального объекта при первом обращении к нему; С другой стороны, get () никогда не возвращает прокси. Выбор между get () и load () прост: если вы уверены, что постоянный объект существует, а его несуществование будет считаться исключительным, load () - хороший вариант. Если вы не уверены, что существует постоянный экземпляр с данным идентификатором, используйте get () и проверьте возвращаемое значение, чтобы убедиться, что оно равно нулю. Использование load () имеет еще одно значение: приложение может получить действительную ссылку (прокси) на постоянный экземпляр, не обращаясь к базе данных для получения ее постоянного состояния. Таким образом, load () может не генерировать исключение, если не находит постоянный объект в кэше или базе данных; исключение будет выброшено позже при доступе к прокси. Конечно, получение объекта по идентификатору не так гибко, как использование произвольных запросов.
Ну, по крайней мере, в nhibernate, session.Get (id) загрузит объект из базы данных, а session.Load (id) только создает для него прокси-объект, не покидая ваш сервер. Работает так же, как и любое другое свойство с отложенной загрузкой в ваших POCO (или POJO :). Затем вы можете использовать этот прокси как ссылку на сам объект для создания отношений и т. Д.
Думайте об этом как об объекте, который хранит только Id и который загрузит все остальное, если вам когда-нибудь понадобится. Если вы просто передаете его для создания отношений (например, FK), идентификатор - это все, что вам когда-либо понадобится.
session.load () всегда будет возвращать «прокси» (термин Hibernate), не обращаясь к базе данных. В Hibernate прокси - это объект с заданным значением идентификатора, его свойства еще не инициализированы, он просто выглядит как временный поддельный объект. Если строка не найдена, генерируется исключение ObjectNotFoundException.
session.get () всегда обращается к базе данных и возвращает реальный объект, объект, представляющий строку базы данных, а не прокси. Если строка не найдена, возвращается значение null.
Производительность с этими методами также влияет на разницу. между двумя ...
Еще один дополнительный балл:
Метод get класса Hibernate Session возвращает null, если объект не найден в кеше, а также в базе данных. в то время как метод load () генерирует исключение ObjectNotFoundException, если объект не найден в кеше, а также в базе данных, но никогда не возвращает значение null.
Одним из косвенных последствий использования 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 немедленно выполнит выбор, и номера версий будут загружены в правильное время для оптимистической проверки блокировки.
Отличное объяснение можно найти на http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load ():
он всегда будет возвращать «прокси» (термин Hibernate) без попадание в базу данных.
В Hibernate прокси - это объект с заданным значением идентификатора, его свойства еще не инициализированы, он просто выглядит как временный поддельный объект.
Он всегда будет возвращать прокси-объект с заданным значением идентификатора, даже если значение идентификатора не существует в базе данных. Однако, когда вы пытаетесь инициализировать прокси, извлекая его свойства из базы данных, он попадет в базу данных с помощью оператора select. Если строка не найдена, генерируется исключение ObjectNotFoundException.
session.get ():
Он всегда попадает в базу данных (если не найден в кеше) и возвращает реальный объект, объект, представляющий строку базы данных, а не прокси.
Если строка не найдена, возвращается значение null.
load () не может найти объект в кеше или базе данных, возникает исключение, и метод load () никогда не возвращает null.
get () метод возвращает null, если объект не может быть найден. Метод load () может возвращать прокси вместо реального постоянного экземпляра. Get () никогда не возвращает прокси.