Java Hibernate 中的 LazyInitializationException:无法初始化代理 - 没有会话

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39054193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:50:56  来源:igfitidea点击:

LazyInitializationException in Hibernate : could not initialize proxy - no Session

javaspringhibernate

提问by Turtle

I call dao from my service as

我从我的服务中调用 dao 作为

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

and in the dao I am getting product as

在 dao 中,我得到的产品是

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

This runs fine but if I change my dao class to

这运行良好,但如果我将 dao 类更改为

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

I get org.hibernate.LazyInitializationException: could not initialize proxy - no Session. The exception occurs in view layer where I am just printing the product. I do not understand why returning in same line in dao method results in exception in view layer but works fine if I save it in a reference and then return that.

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

采纳答案by Sohil

Here's a good referenceto get you familiar with how .get() and .load() method works.

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

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

session.load()by default returns a proxy object without hitting a database. It basically returns NoObjectFoundErrorif there aren't any records on the table or else it will return a reference without populating the actual object or even hitting the database. Your above method returns a proxy and since it has to initialize the your object as well, the session remains open and object is populated.

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

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

But in your second method, basically a proxy is returned without any initialization. session is closed thereafter without any prior use. Thus you get the error.

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

Hope that helps

希望有帮助

回答by Maciej Marczuk

It's a typical problem when you are dealing with Hibernate and view layer. Error happens because Hibernate session is closed before your view is rendered. Two easiest way to fix this is to use Open Session In View pattern OR fetch all data you need in views before view rendering.

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

Since you are using Spring, the first solution is the easiest one - just apply OpenSessionInViewFilter(or OpenEntityManagerInViewFilterif you are using JPA):

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

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

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

You should also read what are the pros and cons of using OSIV pattern.

您还应该阅读使用 OSIV 模式的利弊。

回答by Vivek Goel

This error means that you're trying to access a lazily-loaded property or collection, but the hibernate session is closed or not available . Lazy loading in Hibernate means that the object will not be populated (via a database query) until the property/collection is accessed in code.Hibernate accomplishes this by creating a dynamic proxy object that will hit the database only when you first use the object. In order for this to work, your object must be attached to an open Hibernate session throughout it's lifecycle.

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

If you remove the SOP statement then object is not accessed at all and thus not loaded. And when you try to access it in your other part code of code then it will throw LazyInitializationException.

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

回答by Pierluigi Vernetto

in your Product entity, try adding fetch = FetchType.EAGER in your OneToMany relationship annotation, like

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

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

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

This will load the entire Product object graph, avoiding subsequent calls

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