我在一个简单的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 --尽管是该线程的有效会话(如堆栈跟踪和调试所示)。我不能使用急切的加载,因为这将导致其他地方的问题。我可以检查实体管理器在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()); }
发布于 2012-01-09 11:54:11
仅仅因为一个实体管理器是打开的,并不意味着所有延迟加载的实体都可以被加载。如果实体是由与“当前”实体不同的实体管理器/会话加载的,则实体仍然是分离的,并且尝试在其上加载延迟关联将导致您遇到的异常。
简而言之,您的过滤器打开了一个实体管理器,这使得延迟加载当前请求成为可能。但是,一旦请求结束,实体就会被分离。
要么在第二个请求时重新加载它们,要么将它们重新附加到当前的实体管理器/会话中。
https://stackoverflow.com/questions/8787857
复制相似问题