Reputation: 335
I call dao from my service as
@Override
@Transactional
public Product getProductById(int id) {
return productDao.getProductById(id);
}
and in the dao I am getting product as
@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
@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.
Upvotes: 14
Views: 77469
Reputation: 562
Here's a good reference to get you familiar with how .get() and .load() method works.
@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 NoObjectFoundError
if 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.
@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
Upvotes: 10
Reputation: 2050
in your Product entity, try adding fetch = FetchType.EAGER in your OneToMany relationship annotation, like
@OneToMany(mappedBy = "employee", fetch = FetchType.EAGER)
This will load the entire Product object graph, avoiding subsequent calls
Upvotes: -3
Reputation: 782
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.
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.
Upvotes: 10
Reputation: 3733
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.
Since you are using Spring, the first solution is the easiest one - just apply OpenSessionInViewFilter
(or OpenEntityManagerInViewFilter
if you are using 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
You should also read what are the pros and cons of using OSIV pattern.
Upvotes: 1