Hibernate 3.6 - session.get () против session.load () - PullRequest
9 голосов
/ 08 ноября 2011

Я пытаюсь понять, в чем разница в возвращаемом объекте и поведении Hibernate 3.6 session.get() и session.load().

Из Javadoc :

get ():

Возвращает постоянный экземпляр данного класса сущности с заданный идентификатор или ноль, если такого постоянного экземпляра нет. (Если экземпляр уже связан с сеансом, верните, что пример. Этот метод никогда не возвращает неинициализированный экземпляр.)

load ():

Возвращает постоянный экземпляр данного класса сущности с заданный идентификатор, предполагая, что экземпляр существует. Этот метод может вернуть прокси-экземпляр, который инициализируется по требованию, когда доступ к методу без идентификатора.

У меня три вопроса:

  1. Javadoc не сообщает, когда load() может вернуть прокси - есть ли способ узнать его заранее?

  2. Когда load() возвращает прокси - это означает, что load() не получил доступ к базе данных, я прав? Тогда что если я предоставлю load() идентификатор, которого нет в базе данных? Теперь у меня будет сеанс с недействительным идентификатором (без исключения). Теперь я хочу позволить другому постоянному экземпляру указывать на этот прокси - это будет работать? Для этого сценария мне не нужно инициализировать прокси, мне нужен только его идентификатор (который у меня есть, хотя он недействителен, поскольку его нет в базе данных). Поэтому я предполагаю, что спрашиваю, правильное ли мое описание, и всегда ли мне нужно после load() возвращать возвращаемый объект с помощью isInitialized(), чтобы убедиться, что он представляет действительную сущность (или, по крайней мере, действительный прокси-сервер), т.е. с действительным идентификатором.

  3. Кроме того, что произойдет, если load() вернет прокси - таким образом, прокси - это экземпляр, который уже связан с сеансом. Затем в соответствии с описанием get(): «Если экземпляр уже связан с сеансом, верните этот экземпляр». - так get() возвращает прокси? Поскольку согласно описанию get(): «Этот метод никогда не возвращает неинициализированный экземпляр.»

Спасибо!

UPDATE

Правильно ли следующее?

(A) Я думаю, что и load(), и get() сначала попытаются проверить кэш сеанса перед переходом в БД - поэтому было бы неправильно говорить, что любой из них всегда попадает в БД или всегда возвращает прокси.

(B) Инициализированный прокси-сервер отличается от исходного экземпляра, как вы можете прочитать здесь: http://blog.xebia.com/2008/03/08/advanced-hibernate-proxy-pitfalls/

1 Ответ

18 голосов
/ 08 ноября 2011

(1), (3):

Да.Вы правы. Обе load() и get() сначала проверит, сохранился ли экземпляр с тем же PK в сеансе.

Если да, просто возвращает этот экземпляр из сеанса.(Это может быть прокси или фактический экземпляр класса сущности)

Если нет, load() создаст и вернет прокси, в то время как get() ударит по БД и вернет экземпляр фактического класса сущности.

Возвращенный объект из обоих методов будет связан и сохранен в сеансе позже.

Таким образом, get() или load() возвращаемый прокси или фактический класс сущности зависит от того, используете ли вы get ()или load (), чтобы получить экземпляр того же PK в текущем сеансе в первый раз.

Вы можете проверить это поведение, выполнив следующий тест:

Session session = HibernateUtil.getSessionFactory().openSession();

Item loadItem= (Item ) session.load(Item.class, 1);
System.out.println(loadItem.getClass().getName());

Item getItem = (Item ) session.get(Item .class, 1);
System.out.println(getItem .getClass().getName());

Если это прокси, имя напечатанного класса не будет таким же, как фактическое имя класса сущности.Просто измените порядок выполнения на load() и get(), чтобы увидеть эффект.

(2):

Если load () вернет прокси, он не будет обращаться к БД во времяload(). Прокси будет обращаться к БД только в том случае, если к их сопоставленным свойствам помимо PK обращаются, и с сеансом не связаны экземпляры с таким же значением PK.

После того, как прокси-сервер получит доступ к БД, экземпляр с тем же PK прокси-сервера будет связан с этим сеансом. Так что, когда вы снова получаете другие свойства от прокси-сервера или используете get(), чтобы получить экземпляр длятот же PK, DB не будет доступен, так как значения можно найти в сеансе.

Например:

/**Session starts***/
Item item = (Item) session.load(Item.class, new Long(1));
item.getId();  //Will not access DB as only the identifier property is access
item.getDescription(); // access the DB and initialize the proxy . After that , the item proxy is said to be initialized
item.getPrice(); //will not access DB as the item with the PK 1 can be get from the session
Item item2 = session.get(Item.class, new Long(1)) //will not access DB as the item with the PK 1 can be get from the session

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...