Учитывая следующую ситуацию в веб-приложении:
// 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.