웹 응용 프로그램에서 다음과 같은 상황이 발생했습니다.EntityManager.merge()가 LazyInitializationException을 방지하는 이유는 무엇입니까?
// 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()
에 의해 발생하지 않았 음을 입증했습니다. 이것은 stacktrace의 일부입니다.
at org.hibernate.collection.PersistentList.iterator(PersistentList.java:138)
즉 실제로 문제를 일으키는 반복자입니다. 그리고 점점 더 이상해졌습니다. 첫 번째 경우 (find()
)에서는 hibernate가 영속 컨텍스트의 캐시가 아닌 데이터베이스에서 새 객체를 검색하기 위해 select 문을 실행했는지 확인했습니다.
추가 2
다음은 스택 추적입니다.
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.
감사합니다. lujop하지만이 경우는 아닙니다. 'parent.getId()'를 통해 성공적으로 ID를 얻을 수 있지만 반복이 실패합니다. 내 편집 내용을 확인하십시오. – Zeemee
매우 이상합니다. 자세한 스택 추적을 넣을 수 있습니까? 그리고 코드는 정확히 당신이 넣었거나 단순화 한 것입니까? – lujop
stacktrace를 더 추가했습니다. 나는 약간의 코드를 단순화 시켰지만, 그것은 중요하지 않아야한다. – Zeemee