LazyInitializationException Hibernate Spring Help!!!
hey people,
I was hoping someone can help me out. I am using spring with JPA and Hibernate.
Now I understand you got to do this in your spring bean file:
Code:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
to use the @Transactional annotation at the top of your DAO or Service method calls like so:
Code:
@Transactional
public List<Category> findByName(Object name, int... rowStartIdxAndCount) {
return findByProperty(NAME, name, rowStartIdxAndCount);
}
Here is my problem.
In my Junit test, I do this:
Code:
public void testFindByName() {
categoryDAO = (CategoryDAO)DataAccessServiceFactory.getBean("CategoryDAO");
ICategoryServiceImpl categoryServiceImpl = new ICategoryServiceImpl();
categoryServiceImpl.setICategoryDAO(categoryDAO);
ICategoryService categoryService = categoryServiceImpl;
//List<Category> categories = categoryDAO.findByName("Autos");
List<Category> categories = categoryService.findByName("Autos",null);
for (Category category : categories) {
System.out.println("category: "+category.getName());
System.out.println("****now to get topics if there are any!****");
Set<Topic> topics = category.getTopics();
for (Topic topic : topics) {
System.out.println("topic: "+topic.getTitle());
System.out.println("****now to get submissions if there are any!****");
Set<Submission> submissions = topic.getSubmissions();
for (Submission submission : submissions) {
System.out.println("submission topic: " +submission.getTopic());
System.out.println("submission title: " +submission.getTitle());
}
}
}
}
Basically, I get a list of categories. Each category has Topics. Topics is lazy loaded.
In the Category Domain object, it is defined as:
Code:
@Transactional//(propagation=Propagation.REQUIRED, readOnly=false)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "category")
public Set<Topic> getTopics() {
return this.topics;
}
I probably shouldnt have @Transactional defined above but I was just playing around with that, even without it I still get the same results.
As soon as I try to get Topics, it gives me this exception:
Code:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.logixplayer.project1.domain.Category.topics, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
Yeap you guessed it, the root cause?
"no session or session was closed"
I realize that the session was closed the second I got a list of categories...I understand that...but how does the session stay alive again or come back if I want to lazyload?
I read about this:
Code:
<filter>
<filter-name>Session Filter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
but will OpenSessionInViewFilter allow me to just execute my code like so:
Code:
Set<Topic> topics = category.getTopics();
without exceptions that I am now facing?
Incidentally this is failing in my Junit Test case. I read up on that aswell and came across this:
Code:
AbstractTransactionalSpringContextTests
But am not really sure how to use it...there is some overriding of bean files that I saw...
Basically I am uncertain about what to do and how to resolve this lazyloading exception....
I read that you can wrap everything in one Trasactional Service method...but that defeats the purpose..I want to access the Database when I want to....but then again....I am not sure how to proceed...
Conclusion:
1) Need to get my Junit tests working and be able to see a category and its topics and posts for each topic And not have
Code:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
2) Need to learn if this "fix" for lazyloading - OpenSessionInViewFilter ? will work in a real web app where I could just make calls like this:
Code:
Set<Topic> topics = category.getTopics();
and not worry about lazyloading exceptions
3)any other relevant information to help me out!! Thanks so much
p.s. I think this is just a Spring issue. If I was using pure Hibernate without Spring, I think the call to get topics would work...
Any help is greatly appreciated!!!
Thanks again...
Still no luck, OpenEntityManagerInViewFilter LazyInitializationException HELP!!
Hi people,
I am still battling this LazyInitializationException using JPA+Spring+Hibernate.
I have followed suggestions such as
1) move the filter definition for OpenEntityManagerInViewFilter to the top of the web.xml file so to be the first filter to intercept calls
2)Observe log files to see if the OpenEntityManagerInViewFilter is firing. It looks like it is:
Code:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.logixplayer.pf.domain.Category.topics, no session or session was closed
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
com.logixplayer.pf.category.controller.CategoryController.onSubmit(CategoryController.java:38)
org.springframework.web.servlet.mvc.SimpleFormController.onSubmit(SimpleFormController.java:409)
org.springframework.web.servlet.mvc.SimpleFormController.onSubmit(SimpleFormController.java:381)
org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission(SimpleFormController.java:267)
org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:265)
org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:112)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
I am missing something but I do not know what!
I know why I am getting the exception as I stated in my earlier post. The session is being closed when I try to access children (topics) of each category (parent). This is why I was trying to use OpenEntityManagerInViewFilter in the first place.
My only hunch is that the sessions are not unique but distinct. I.e. the session that is being used to get Categories is not being kept open for some reason.
In my web.xml, I declare this:
Code:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
<!-- classpath:applicationContext.xml -->
<!-- classpath:/data-access-context.xml -->
classpath:data-access-context.xml
</param-value>
</context-param>
which references my entityManagerFactory like so:
data-access-context.xml:
Code:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="dataAccessPU" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory"
ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
The only thing that jumps out at me is the class definition for OpenEntityManagerInViewFilter:
Code:
Servlet 2.3 Filter that binds a JPA EntityManager to the thread for the entire processing of the request. Intended for the "Open EntityManager in View" pattern, i.e. to allow for lazy loading in web views despite the original transactions already being completed.
Servlet 2.3???
I am using Servlet 2.5 and JSP 2.1.
Does OpenEntityManagerInViewFilter not work for servlet 2.5 specs??
I am totally stumped
Anyone can lend some help? Please do...I have been stuck for a very long time :)
Thanks so much!!
Hibernate + Spring + JPA --> Lazyloadexception
Hi,
the point of this exercise is to actually not take a performance hit.
There will be potentially thousands of users at one single time, I cannot afford to load EAGER. because then each user will have the same categories and the same topics in memory.
I need to figure out how to load lazy.
I have searched thoroughly on the net but cannot find a solution to this problem, even though it is quite a common issue.
I thought the OpenEntityManagerInViewFilter needed to be simply plugged in...
I really need some help on this one...please reach out...
thanks again
OpenEntityManagerInViewFilter LazyInitializationException HELP!!
Hi, let me start by pinpointing this problem again.
In my CategoryController (Spring MVC) I am trying to lazy load topics, other categories, i.e. anything that has been declared as fetch = FetchType.LAZY in my AbstractCategory domain object:
Code:
@MappedSuperclass
public abstract class AbstractCategory implements java.io.Serializable {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "category")
public Set<Category> getCategories() {
return this.categories;
}
public void setCategories(Set<Category> categories) {
this.categories = categories;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "category")
public Set<Topic> getTopics() {
return this.topics;
}
Note: I used the myEclipse reverse generate tool to create my DAO's and domain objects.
Now, moving on to my controller. First of all, the reason why I tried to use annotations was because of its elegance. I really don't want to use programmatic style transaction demarcations (and I am sure there is a solution to this using annotations)
In the controller below, just like the issue I was getting when I tried to lazily get Topics, in this case I am trying to get more categories of the parent category BUT I get a LazyLoadingException.
Code:
public class CategoryController extends SimpleFormController {
public ModelAndView onSubmit(Object command) throws ServletException {
CategoryBean categoryBean = (CategoryBean) command;
System.out.println("the name from the command bean is: "+categoryBean.getName());
// call category service
//iCategoryService
ICategoryService categoryService = (ICategoryService)DataAccessServiceFactory.getBean("iCategoryService");
ITopicService topicService = (ITopicService)DataAccessServiceFactory.getBean("iTopicService");
List<Category> categories = categoryService.findByName("Autos", null);
// should only be one category in actuality
for (Category category : categories) {
System.out.println("category: "+category.getName());
Set<Category> subCategories = category.getCategories(); LAZY EXCEPTION HERE
for (Category subCategory : subCategories) {
System.out.println("subCategory: "+subCategory.getName());
//Set<Topic> topics = subCategory.getTopics();
List<Topic> topics = topicService.findByCategoryID(subCategory.getCategoryId(), null);
System.out.println("****now to get topics if there are any!****");
for (Topic topic : topics) {
System.out.println("topic: "+topic.getTitle());
System.out.println("****now to get submissions if there are any!****");
Set<Submission> submissions = topic.getSubmissions();
for (Submission submission : submissions) {
System.out.println("submission topic: " +submission.getTopic());
System.out.println("submission title: " +submission.getTitle());
}
}
}
}
Note, I tried to hack this thing by avoiding:
Code:
//Set<Topic> topics = subCategory.getTopics();
because I was getting a lazy exception, I thought I could just create my topic service (because it is declared @Transactional) and then pass the sub-categoryID
Code:
List<Topic> topics = topicService.findByCategoryID(subCategory.getCategoryId(), null);
but same deal, the second I tried to get sub-categories for my category, it choked, got the lazy load exception again...
kesa, you are absolutely correct about findbyname and the session being closed. In my categoryService, I do the following:
Code:
public class ICategoryServiceImpl implements ICategoryService{
@Transactional(propagation=Propagation.REQUIRED, readOnly=true)
public List<Category> findByName(Object name, int[] rowStartIdxAndCount){
List<Category> result = iCategoryDAO.findByName(name,rowStartIdxAndCount);
return result;
}
Essentially, my method findByName is declared:
Code:
@Transactional(propagation=Propagation.REQUIRED, readOnly=true)
This is why this works:
Code:
List<Category> categories = categoryService.findByName("Autos", null);
but when the minute I start looping through the categories to get sub-categories of each category:
Code:
Set<Category> subCategories = category.getCategories();
I get:
Code:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.logixplayer.pf.domain.Category.categories, no session or session was closed
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:583)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:112)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.logixplayer.pf.domain.Category.categories, no session or session was closed
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
com.logixplayer.pf.category.controller.CategoryController.onSubmit(CategoryController.java:43)
org.springframework.web.servlet.mvc.SimpleFormController.onSubmit(SimpleFormController.java:409)
org.springframework.web.servlet.mvc.SimpleFormController.onSubmit(SimpleFormController.java:381)
org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission(SimpleFormController.java:267)
org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:265)
org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:112)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
Yes the session is being closed which is why I am trying to use OpenEntityManagerInViewFilter to begin with!
I am not clear on your first suggestion about t.callMethod();
The actual error is happening when I try to get a lazy collection. (not after when I iterate over topics or categories)
How can I bind to the original entityManager session? i.e. the one that was used for (using annotations):
Code:
List<Category> categories = categoryService.findByName("Autos",null);
because it is closed after this call: categoryService.findByName
Essentially what I want to do is Set<Category> subCategories = category.getCategories(); and just move on.
Great exercise but can we just resolve this now??
Thanks :)
JPA Hibernate Spring Help!
I thought I communicated that, I am using OpenEntityManagerInViewFilter but its not working, which is why I am getting this lazyloadingexception.
Can someone post a working example or just tell me what's going wrong here??
Appreciate it, thank you.
JPA Hibernate Spring Help!
Quote:
Originally Posted by
duardito
maybe I am wrong but I believe your problem is because you have your code inside CategoryController, if "public ModelAndView onSubmit(Object command)" is not a transactional method, then all calling methods inside are REQUIRED, so, each method is independent in each transaction, so each method close itself transaction when it ends.
I would recomend to make other method including all problematic code and then pass this method to controller.
IMHO.
Perhaps what you are trying to say is that there should only be one overall transaction in the controller?
Regardless, even if there was one transaction in the controller, my problem still stands, observe:
Code:
List<Category> categories = categoryService.findByName("Autos", null);
// should only be one category in actuality
for (Category category : categories) {
System.out.println("category: "+category.getName());
Set<Category> subCategories = category.getCategories(); LAZY EXCEPTION HERE
Let's just say all I had was the above in my controller in "some other method".
The point is that the session from
Code:
categoryService.findByName("Autos", null);
is closed right after this call (to findByName)
Scenario: I got my OpenEntityManagerInViewFilter hooked up.
Question: How do I re-attach to the same session just used in categoryService.findByName("Autos", null); so I avoid the LAZY LOAD EXCEPTION when I do:
Code:
Set<Category> subCategories = category.getCategories();
Common guys, what am I missing :P
I thought OpenEntityManagerInViewFilter was as simple as declaring it in web.xml. I got my services annotated with @Transactional YET there is something that is mis-configured, not configured or just missing.
I am not sure to say Help?? or Help!!
Gosh this is the best one yet...