为什么EntityManager.merge()阻止了LazyInitializationException而EntityManager.find()却没有?

时间:2010-12-01 15:38:27

标签: java hibernate

考虑到Web应用程序中的以下情况:

// 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语句来从数据库中检索新对象,而不是从持久化上下文的缓存中检索。

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 :(得分:0)

我认为您的问题不在迭代部分,因为您使用新近加载的父级进行迭代。 问题必须是.getId()似乎没有加载,然后合并工作,因为不要调用.getId()