更好的解决方案,以避免" org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话"在懒惰的模型

时间:2014-08-11 18:13:07

标签: hibernate java-ee jpa-2.0 cdi

“Tipo”有一个“Profissão:”

@ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_profissao", nullable = false)
    public Profissao getProfissao() {
    return profissao;
    }

当我尝试在关系实体Tipo和Profissao相关的数据表视图数据中时:

  <p:dataTable var="lista" value="#{tipoBean.tipos}" id="tabelaTipos"
            rows="10" paginator="true" widgetVar="tabelaTipos">

            <p:column headerText="Profissão">
                <h:outputText value="#{lista.profissao.nome}" />


</p:dataTable>

DAO:

 Criteria cri = session.createCriteria(Tipo.class)
                     .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                     .addOrder(Order.asc("nome"));

  return cri.list();

我在这里广泛讨论了这个错误:      org.hibernate.LazyInitializationException:无法初始化代理 - 无会话

所以我使用“Hibernate.initialize”方式实现了这个。

Criteria cri = session.createCriteria(Tipo.class)
                     .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                     .addOrder(Order.asc("nome"));

            List<Tipo> tipos = (List<Tipo>) cri.list();

            for (Tipo t :tipos) {
                Hibernate.initialize(t.getProfissao()); 

            }

它有效,但有更好的解决方案吗?我不想使用Eager解决方案。任何解决方案?

谢谢!

1 个答案:

答案 0 :(得分:1)

首先,您需要确定页面/表格所需的日期。这个数据需要以某种方式通过hibernate从db中获取,无论是通过连接还是单独的选择或查询。

现在您有两个选择:

  1. 在将对象返回到视图层之前获取服务层中的数据。为此,您可以在查询中指定FetchMode s(加入或选择),或使用Hibernate.initialize
  2. 在视图策略中使用开放会话。使用此解决方案,视图可以通过遍历对象模型来加载其他数据。如果以前未加载关联,但视图调用getter,则hibernate将初始化代理。
  3. 第二种选择 专业版:更灵活:如果您稍后在视图中需要更多数据,则无需更改服务层。这是因为服务层负责人不知道使用了什么数据。 Con:很难找到性能问题:由于视图在必要时加载数据,因此在服务层完成其工作后可能会加载大量数据。通过添加拦截器,通常可以轻松地完成服务层中的响应时间测量。根据您的视图技术,测量渲染时间可能会更加困难。