【问题标题】:failed to lazily initialize a collection of role懒惰地初始化角色集合失败
【发布时间】:2011-07-21 05:57:43
【问题描述】:

您好,我有两个这样的课程:

public class Indicator implements Serializable {
...

    @OneToMany(mappedBy = "indicator",fetch=FetchType.LAZY)
    private List<IndicatorAlternateLabel>  indicatorAlternateLabels;

    public List<IndicatorAlternateLabel> getIndicatorAlternateLabels() {
        return indicatorAlternateLabels;
    }

        public void setIndicatorAlternateLabels(List<IndicatorAlternateLabel> indicatorAlternateLabels) {
            this.indicatorAlternateLabels = indicatorAlternateLabels;
        }
...
    }

public class IndicatorAlternateLabel implements Serializable {
...
 @ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
    @JoinColumn(name = "IndicatorID")
    @XmlTransient
    private Indicator indicator;
...
}

当我这样使用它们时:

 public MetricTypeDetail getMetricTypeDetail(Integer metricTypeId) {
        Criteria crit = sessionFactory.getCurrentSession().createCriteria(Indicator.class, "sub")
                    .add(Restrictions.eq("number", metricTypeId))
                    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).setCacheable(true);
        crit.setMaxResults(1);
        Indicator indicator=(Indicator) crit.uniqueResult();
        MetricTypeDetail metricTypeDetail=new MetricTypeDetail(indicator);
        List<IndicatorAlternateLabel> indicatorAlternateLabels = null;
        indicatorAlternateLabels=indicator.getIndicatorAlternateLabels();
        metricTypeDetail.setIndicatorAlternateLabels(indicatorAlternateLabels);
        return metricTypeDetail;
    }

此代码返回异常: 未能延迟初始化角色集合:com.porism.service.domain.Indicator.indicatorAlternateLabels,没有会话或会话已关闭

有什么想法吗?我对 Hibernate 很陌生

【问题讨论】:

    标签: java hibernate


    【解决方案1】:

    当您获取通常包含延迟加载的集合的对象并尝试访问该集合时,会发生延迟异常。

    你可以通过

    避免这个问题
    • 访问事务中的惰性集合。
    • 使用Hibernate.initialize(obj); 初始化集合
    • 在另一个事务中获取集合
    • 使用Fetch profiles 选择惰性/非惰性获取运行时
    • 将 fetch 设置为 non-lazy(一般不推荐)

    此外,我建议您查看右侧的 related 链接,该问题之前已多次回答。另见Hibernate lazy-load application design

    【讨论】:

    • Fetching 意味着使用 JPQL 进行查询,我认为仅使用事务通过集合检索关联是行不通的
    【解决方案2】:

    您可能没有获取 Joined Set。请务必在您的 HQL 中包含该集合:

    public List<Node> getAll() {
        Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery("FROM Node as n LEFT JOIN FETCH n.nodeValues LEFT JOIN FETCH n.nodeStats");
        return  query.list();
    }
    

    您的班级有 2 套,例如:

    public class Node implements Serializable {
    
    @OneToMany(fetch=FetchType.LAZY)
    private Set<NodeValue> nodeValues;
    
    @OneToMany(fetch=FetchType.LAZY)
    private Set<NodeStat> nodeStats;
    
    }
    

    【讨论】:

      【解决方案3】:

      尝试将 fetchType 从 LAZY 切换为 EAGER

      ...
      @OneToMany(fetch=FetchType.EAGER)
      private Set<NodeValue> nodeValues;
      ...
      

      但在这种情况下,您的应用无论如何都会从数据库中获取数据。 如果此查询非常困难 - 这可能会影响性能。 更多在这里: https://docs.oracle.com/javaee/6/api/javax/persistence/FetchType.html

      ==> 73

      【讨论】:

        【解决方案4】:

        建议here解决著名的LazyInitializationException是以下方法之一:

        (1) 使用 Hibernate.initialize

        Hibernate.initialize(topics.getComments());

        (2) 使用 JOIN FETCH

        您可以在 JPQL 中使用 JOIN FETCH 语法来显式提取子集合。这有点像 EAGER 抓取。

        (3) 使用 OpenSessionInViewFilter

        LazyInitializationException 经常发生在视图层。如果你使用 Spring 框架,你可以使用 OpenSessionInViewFilter。但是,我不建议您这样做。如果使用不当,可能会导致性能问题。

        【讨论】:

          猜你喜欢
          • 2017-03-11
          • 1970-01-01
          • 1970-01-01
          • 2019-01-23
          • 2011-10-23
          • 2018-05-31
          相关资源
          最近更新 更多