我在一个简单的webapp上使用wicket和hibernate(jpa) Task.java与Load.java相关,如下所示:
Task.java:
@ManyToOne( targetEntity=Load.class, optional=true, fetch=FetchType.LAZY)
@JoinColumn(name="load_id")
public Load getLoad() {
return load;
}
一个任务可以有一个最大负载,但一个负载可以映射到许多任务:
Load.java:
@OneToMany( mappedBy="load",targetEntity=Task.class, orphanRemoval=false)
public Set<Task> getTasks() {
return tasks;
}
正在创建会话(JPA中的entityManager)并通过事务过滤器附加到线程。
我有一个列出任务的页面,并显示第一个10.当我点击指向下一个10的链接时,它会尝试加载任务11-20的加载(使用getLoad),并且出于某种原因抛出一个LazyInitializationException - 即使是该线程的有效会话(可以在堆栈跟踪和调试器中看到)。我不能使用EAGER加载,因为这会在其他地方引起问题。我可以检查实体管理器在LinkPanel的构造函数中是否有效,它确实有效。但是3行之后它会抛出一个LazyInitializationException。这是怎么回事?
- could not initialize proxy - no Session
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.xxx.er.batch.beans.Load_$$_javassist_7.toString(Load_$$_javassist_7.java)
at com.xxx.er.basman.model.LinkPanel.<init>(LinkPanel.java:41)
at com.xxx.er.basman.pages.TasksOverviewPage$7.populateItem(TasksOverviewPage.java:130)
at org.apache.wicket.extensions.markup.html.repeater.data.grid.AbstractDataGridView.populateItem(AbstractDataGridView.java:187)
at org.apache.wicket.markup.repeater.RefreshingView$1.newItem(RefreshingView.java:114)
at org.apache.wicket.markup.repeater.DefaultItemReuseStrategy$1.next(DefaultItemReuseStrategy.java:71)
at org.apache.wicket.markup.repeater.DefaultItemReuseStrategy$1.next(DefaultItemReuseStrategy.java:68)
at org.apache.wicket.markup.repeater.RefreshingView.addItems(RefreshingView.java:189)
at org.apache.wicket.markup.repeater.RefreshingView.onPopulate(RefreshingView.java:98)
at org.apache.wicket.markup.repeater.AbstractRepeater.onBeforeRender(AbstractRepeater.java:131)
at org.apache.wicket.markup.repeater.AbstractPageableView.onBeforeRender(AbstractPageableView.java:121)
at org.apache.wicket.Component.internalBeforeRender(Component.java:1066)
at org.apache.wicket.Component.beforeRender(Component.java:1100)
at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1754)
at org.apache.wicket.Component.onBeforeRender(Component.java:3966)
at org.apache.wicket.Component.internalBeforeRender(Component.java:1066)
at org.apache.wicket.Component.beforeRender(Component.java:1100)
at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1754)
at org.apache.wicket.Component.onBeforeRender(Component.java:3966)
at org.apache.wicket.Component.internalBeforeRender(Component.java:1066)
at org.apache.wicket.Component.beforeRender(Component.java:1100)
at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1754)
at org.apache.wicket.Component.onBeforeRender(Component.java:3966)
at org.apache.wicket.Page.onBeforeRender(Page.java:1550)
at org.apache.wicket.Component.internalBeforeRender(Component.java:1066)
at org.apache.wicket.Component.beforeRender(Component.java:1100)
at org.apache.wicket.Component.prepareForRender(Component.java:2292)
at org.apache.wicket.Page.prepareForRender(Page.java:1540)
at org.apache.wicket.Component.prepareForRender(Component.java:2329)
at org.apache.wicket.Page.renderPage(Page.java:911)
at org.apache.wicket.protocol.http.WebRequestCycle.redirectTo(WebRequestCycle.java:201)
at org.apache.wicket.request.target.component.PageRequestTarget.respond(PageRequestTarget.java:58)
at org.apache.wicket.request.AbstractRequestCycleProcessor.respond(AbstractRequestCycleProcessor.java:105)
at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1258)
at org.apache.wicket.RequestCycle.step(RequestCycle.java:1329)
at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1436)
at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:486)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:319)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
at com.xxx.er.basman.HibernateTransactionFilter.doFilter(HibernateTransactionFilter.java:58)
为了重新迭代,HibernateTransactionFilter创建了一个这样的EntityManager:
EntityManager em = myEntityManagerFactory.createEntityManager();
em.getTransaction().begin();
entityManagerThreadLocal.set(em);
在LinkPanel构造函数中,我按如下方式检查此EntityManager:
EntityManager em = entityManagerThreadLocal.get();
if (em == null) {
throw new NullPointerException("No entity manager has been started on this thread: " + Thread.currentThread().getName());
}
答案 0 :(得分:4)
仅仅因为实体管理器是开放的并不意味着可以加载所有延迟加载的实体。如果实体已由“当前”实体管理器/会话加载,则实体仍然是分离的,并且尝试在它们上加载延迟关联将导致您遇到的异常。
简而言之,您的过滤器会打开一个实体管理器,它可以为当前请求进行延迟加载。但是一旦请求结束,实体就会分离。
在第二个请求中重新加载它们,或者将它们重新连接到当前的实体管理器/会话。