З API я бачив, що це пов’язано з проксі. Але я не зміг знайти багато інформації про проксі і не розумію різниці між дзвінком session.get
та session.load
. Хтось може пояснити або направити мене на посилальну сторінку?
Дякую!!
Відповіді:
З форуму про сплячий режим :
Це з книги Hibernate in Action. Хороший прочитав це ..
Отримання об’єктів за ідентифікатором Наступний фрагмент коду Hibernate отримує об’єкт користувача з бази даних:
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 :). Потім ви можете використовувати цей проксі як посилання на сам об’єкт для створення зв’язків тощо.
Подумайте про це, як про наявність об’єкта, який зберігає лише ідентифікатор, і який завантажить решту, якщо вам коли-небудь знадобиться. Якщо ви просто передаєте його для створення стосунків (наприклад, FK), ідентифікатор - це все, що вам коли-небудь знадобиться.
session.load () завжди повертає "проксі" (термін Hibernate), не потрапляючи в базу даних. У сплячому режимі проксі - це об’єкт із заданим значенням ідентифікатора, його властивості ще не ініціалізовані, він просто виглядає як тимчасовий фальшивий об’єкт. Якщо жодного рядка не знайдено, він викличе ObjectNotFoundException.
session.get () завжди потрапляє в базу даних і повертає реальний об'єкт, об'єкт, який представляє рядок бази даних, а не проксі. Якщо рядок не знайдено, він повертає значення null.
Ефективність цих методів також різниться. між двома ...
Ще одна зайва точка:
get метод класу Hibernate Session повертає null, якщо об'єкт не знайдено в кеші, а також у базі даних. в той час як метод load () викидає ObjectNotFoundException, якщо об’єкт не знайдено в кеші, а також у базі даних, але ніколи не повертає null.
Одним непрямим наслідком використання "load" замість "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 негайно видасть вибір, а номери версій будуть завантажені в потрібний час для оптимістичної перевірки блокування.
Прекрасне пояснення можна знайти за адресою http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load ():
воно завжди повертає "проксі" (термін сплячого режиму) без потрапляння в базу даних.
У сплячому режимі проксі - це об’єкт із заданим значенням ідентифікатора, його властивості ще не ініціалізовані, він просто виглядає як тимчасовий фальшивий об’єкт.
Він завжди потрапляє в базу даних (якщо її не знайти в кеші) і повертає реальний об'єкт, об'єкт, який представляє рядок бази даних, а не проксі.
Якщо рядок не знайдено, він повертає значення null.
Він завжди повертає об'єкт-проксі із заданим значенням ідентичності, навіть значення ідентичності не існує у базі даних. Однак при спробі ініціалізувати проксі, отримавши його властивості з бази даних, він потрапить у базу даних із оператором select. Якщо не знайдено жодного рядка, викине ObjectNotFoundException.
session.get ():
load () не може знайти об'єкт з кешу чи бази даних, викидається виняток і метод load () ніколи не повертає значення null.
метод get () повертає значення null, якщо об’єкт не вдається знайти. Метод load () може повертати проксі замість реального постійного екземпляра get () ніколи не повертає проксі.