【问题标题】:LazyInitializationException in Hibernate : could not initialize proxy - no SessionHibernate 中的 LazyInitializationException:无法初始化代理 - 没有会话
【发布时间】:2016-12-27 12:13:12
【问题描述】:

我将 dao 从我的服务中称为

@Override
@Transactional
public Product getProductById(int id) {
    return productDao.getProductById(id);
}

在 dao 中,我得到的产品是

@Override
public Product getProductById(int id) {
    Product p = sessionFactory.getCurrentSession().load(Product.class, id);
    System.out.print(p);
    return p;
}

这运行正常,但如果我将我的 dao 类更改为

@Override
public Product getProductById(int id) {
    return sessionFactory.getCurrentSession().load(Product.class, id);
}

我得到 org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话。异常发生在我刚刚打印产品的视图层中。我不明白为什么在 dao 方法中返回同一行会导致视图层出现异常,但如果我将其保存在引用中然后返回它,则可以正常工作。

【问题讨论】:

    标签: java spring hibernate


    【解决方案1】:

    这是一个很好的reference,可以让您熟悉 .get() 和 .load() 方法的工作原理。

    @Override
    public Product getProductById(int id) {
        Product p = sessionFactory.getCurrentSession().load(Product.class, id);
        return p;
    }
    

    session.load() 默认返回一个代理对象而不访问数据库。如果表上没有任何记录,它基本上返回NoObjectFoundError,否则它将返回一个引用而不填充实际对象甚至访问数据库。 您的上述方法返回一个代理,并且由于它还必须初始化您的对象,因此会话保持打开状态并填充对象。

    @Override
    public Product getProductById(int id) {
        return sessionFactory.getCurrentSession().load(Product.class, id);
    }
    

    但是在您的第二种方法中,基本上是在没有任何初始化的情况下返回了一个代理。会话在没有任何事先使用的情况下关闭。因此你得到错误。

    希望有帮助

    【讨论】:

      【解决方案2】:

      这个错误意味着你试图访问一个延迟加载的属性或集合,但休眠会话已关闭或不可用。 Hibernate 中的延迟加载意味着在代码中访问属性/集合之前,不会填充对象(通过数据库查询)。 Hibernate 通过创建一个动态代理对象来实现这一点,该对象仅在您第一次使用该对象时才会访问数据库。为了使其工作,您的对象必须在其整个生命周期内附加到打开的 Hibernate 会话。

      如果您删除 SOP 语句,则根本不会访问对象,因此不会加载。当您尝试在其他部分代码中访问它时,它会抛出 LazyInitializationException。

      【讨论】:

      • 什么是SOP声明?
      【解决方案3】:

      当您处理 Hibernate 和视图层时,这是一个典型的问题。发生错误是因为 Hibernate 会话在您的视图呈现之前已关闭。解决此问题的两种最简单方法是使用 Open Session In View 模式或在视图渲染之前获取视图中所需的所有数据。

      由于您使用的是 Spring,所以第一个解决方案是最简单的解决方案 - 只需申请 OpenSessionInViewFilter(或 OpenEntityManagerInViewFilter,如果您使用的是 JPA):

      http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.html http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.html

      您还应该阅读使用 OSIV 模式的优缺点。

      【讨论】:

        【解决方案4】:

        在您的 Product 实体中,尝试在您的 OneToMany 关系注释中添加 fetch = FetchType.EAGER,例如

        @OneToMany(mappedBy = "employee", fetch = FetchType.EAGER)

        这将加载整个 Product 对象图,避免后续调用

        【讨论】:

        • Eager fetch 类型不会避免后续调用。
        猜你喜欢
        • 2018-09-28
        • 2019-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-09
        • 2017-08-13
        • 2014-11-28
        • 2019-12-11
        相关资源
        最近更新 更多