2011-07-26 62 views
1

集合我怕我会错过一个非常基本的观点,但我坚持的那一刻,希望有人能在这点我的眼睛主演硬到正确的选择。 我尝试通过我的应用程序设置一步一步,让自己清晰(希望人们不会在他们到达发布结束前感到无聊):异常而加载懒洋洋地从实体

我有一个会话作用域CDI组件作为JSF处理程序2.0视图。它拥有一个实体管理器,对象列表和一个特殊的单个对象:

Query query = em.createQuery("select e from MyEvent e"); 
events = (ArrayList<MyEvent>) query.getResultList(); 

@Named 
@SessionScoped 
public class EventHandler implements Serializable { 

    @PersistenceContext 
    private EntityManager em; 

    private List<MyEvent> events; 

    private MyEvent currentEvent; 
    ... 

当视图请求列表中显示的表,它通过查询数据库填充列表该视图显示了这种在一个数据表,并提供该处理程序中的链接到动作方法:

<h:dataTable value="#{eventHandler.events}" var="_var"> 
    ... 
    <h:commandLink action="#{eventHandler.linkAction(_var)}"> ... </h:commandLink> 

动作方法存储参考:

public void setCurrentEvent(MyEvent currentEvent) { 
    this.currentEvent = currentEvent; 
    ... 

内搜集和上述文献中使用的实体,它会直接默认延迟加载there'a关系:

@ManyToMany(mappedBy="supportedServices") 
public Set<MyEntity> getSupportingEntities() { 
    ... 

现在,在详细视图是和试图访问这个关系时这样做的:

#{eventHandler.currentEvent.supportingEntities...} 

我得到一个org.hibernate.LazyInitializationException告诉我,会话关闭。

不宜处理程序能够装载在第二视图稍后的请求的关系,当处理程序是会话范围,并通过加载查询的引用?

回答

1

嗯,我想这是因为persistenceContext,事件,如果它是一个会话的成员范围的bean,不会话范围。
当视图被称为第一时间,创建一个持久上下文,实体(事件)被加载并填充数据表。然后持久化上下文被刷新,关闭并且响应被发送到客户端。这一切都发生在同一个http请求中。

但是当你调用细节来看,另一个HTTP请求发出,并创建另一个持久化上下文,和你提到“currentEvent”没有更多的附加在最后的持久化上下文。因此,LazyInitializationError(该实体必须进行管理,以延迟加载)。

解决方案可能是:

  • 使用扩展的持久化上下文(explained here)。
  • 渴望获取的关系:

    @ManyToMany(mappedBy="supportedServices", fetch=FetchType.EAGER)

  • 合并currentEvent的脱管的实例在细节上使用它之前查看:

    entityManager.merge(currentEvent);

+0

谢谢你的提示。但是既没有使用type = PersistenceContextType.EXTENDED,也没有将它合并到em中,而且在映射中使用预先获取是不成问题的。但是我看到,如果我在动作处理程序中设置currentEvent时触及关系,它就会起作用。不过,我不明白为什么他们以后不能加载实体的一部分。 –

+0

因为我还找不到其他解释,我会接受你的答案。 –

相关问题