我担心我会错过一个非常基本的观点,但我现在已经陷入困境,希望有人可以指出我的眼睛主演,努力向右迈进...... 我尝试逐步完成我的应用程序设置,以使自己清楚(希望人们在发布结束之前不会觉得无聊):
我有一个会话范围的CDI组件,用作JSF 2.0视图的处理程序。它包含一个实体管理器,一个对象列表和一个特殊的单个对象:
@Named
@SessionScoped
public class EventHandler implements Serializable {
@PersistenceContext
private EntityManager em;
private List<MyEvent> events;
private MyEvent currentEvent;
...
当视图请求列表显示表时,它通过查询数据库来填充列表:
Query query = em.createQuery("select e from MyEvent e");
events = (ArrayList<MyEvent>) query.getResultList();
视图在数据表中显示了这一点,并提供了处理程序中操作方法的链接:
<h:dataTable value="#{eventHandler.events}" var="_var">
...
<h:commandLink action="#{eventHandler.linkAction(_var)}"> ... </h:commandLink>
action方法存储引用:
public void setCurrentEvent(MyEvent currentEvent) {
this.currentEvent = currentEvent;
...
在上面的集合和引用中使用的实体中,默认情况下存在一种懒惰加载的关系:
@ManyToMany(mappedBy="supportedServices")
public Set<MyEntity> getSupportingEntities() {
...
现在,当进入详细视图并尝试通过执行以下操作来访问此关系时:
#{eventHandler.currentEvent.supportingEntities...}
我收到org.hibernate.LazyInitializationException,告诉我会话已关闭。
当处理程序是会话作用域并通过查询加载引用时,处理程序是否应该能够在第二个视图中的稍后加载所请求的关系?
答案 0 :(得分:1)
嗯,我认为这是因为persistenceContext事件(如果它是会话范围bean的成员)不是会话作用域。
在第一次调用视图时,将创建持久性上下文,加载实体(事件)并填充数据表。然后刷新,关闭持久化上下文,并将响应发送到客户端。这一切都发生在同一个http请求中。
但是当您再调用详细信息视图时,会发出另一个http请求,并创建另一个持久性上下文,并且您对“currentEvent”的引用不再附加到上一个持久性上下文。因此,LazyInitializationError(必须将实体管理为延迟加载)。
解决方案可能是:
渴望获取关系:
@ManyToMany(mappedBy="supportedServices", fetch=FetchType.EAGER)
在详细信息视图中使用之前合并currentEvent的分离实例:
entityManager.merge(currentEvent);