Почему EntityManager.merge () предотвращает LazyInitializationException, а EntityManager.find () - нет? - PullRequest
2 голосов
/ 01 декабря 2010

Учитывая следующую ситуацию в веб-приложении:

// EntityManager em, one per Request with Spring's OpenEntityManagerInViewFilter
// Parent oldParent, from previous request (and therefore another persistence context)
Parent parent = em.find(Parent.class, oldParent.getId());
List<Child> children = parent.getChildren(); // Mapped collection with LazyLoading
for (Child child : children) {
     ...

Вызов итератора списка вызывает LazyInitializationException.Это сбивает с толку, потому что выборка списка детей происходит в том же контексте постоянства (или я ошибаюсь?). Но , используя merge(), все работает.Как будто два запроса совместно используют один постоянный контекст.

Parent parent = em.merge(oldParent);
List<Child> children = parent.getChildren();
for (Child child : children) {
     ...
// No Exception!!

В чем моя ошибка в рассуждениях?

Добавление
Я доказал, что ошибкане вызвано parent.getId().Это часть трассировки стека:

at org.hibernate.collection.PersistentList.iterator(PersistentList.java:138)

Это означает, что именно итератор вызывает проблему.И это становится еще более странным - я проверил, что в первом случае (с find()) оператор hibernate выдает оператор select для извлечения нового объекта из базы данных, а не из кэша контекста постоянства.

Addition2
Вот немного больше трассировки стека:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: edeka.sw.phb.model.Chapter.subChapters, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
    at org.hibernate.collection.PersistentList.iterator(PersistentList.java:138)
    at java.util.Collections$UnmodifiableCollection$1.<init>(Collections.java:1022)
    at java.util.Collections$UnmodifiableCollection.iterator(Collections.java:1021)
    //... followed by the line of the foreach.

1 Ответ

0 голосов
/ 01 декабря 2010

Я думаю, что ваша проблема не в итерационной части, потому что вы выполняете итерацию с новым недавно загруженным родителем. Проблема должна быть в .getId (), который, кажется, не загружен, тогда слияние работает, потому что не вызывайте .getId ()

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