Announcement Announcement Module
Collapse
No announcement yet.
LazyInitializationException Hibernate Spring Help!!! Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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...

  • #2
    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!!

    Comment


    • #3
      A fix for this might be:
      Code:
      @Transactional//(propagation=Propagation.REQUIRED, readOnly=false)
      	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "category")
      	public Set<Topic> getTopics() {
      		return this.topics;
      	}
      If you change
      fetch = FetchType.LAZY
      to
      fetch = FetchType.EAGER
      This will preload all your Topic objects into the Set so that they can be used later. Note this does mean that the Set will always be pre-populate from the database weather you use this Set or not.

      Comment


      • #4
        Hibernate + Spring + JPA --&gt; 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

        Comment


        • #5
          Hi,

          Ok, so we are dealing with "Detachment". This can happen in many ways i.e. when an entity is serialized,
          when a rollback occurs etc.. In your case I believe it is because @Transactional for findByName method has finished.

          One solution to this is to trigger Lazy Loading: (this would be done in the findByName method as it is annotated with @Transaction)
          Code:
          Set<Topic> topics = category.getTopics();
          Iterator itr = topics.iterator();
          while(...) {
          	Topic t = (Topic) itr.next();
          	t.callMethod();
          }
          Here you need to invoke a method on the getTopics as Lazy Loading relationship may be a proxy that will not load
          the entity. We have to call a method (t.callMethod()) on the entity to ensure that it is really pulled from the database.


          Another way is to change the way you are using Transactions, currently the entity manager created by the @Transaction
          only remains open as long as the transaction in which it was created has not finished. So you need to wrap the transaction around the class
          using the findByName ensuring any calls made to detached entities are made within this method. So an example would be:

          Code:
          ....
          @Resource 
          UserTransaction tx;
          
          public void someMethod() throws Exception {
          //....
          try {
          	tx.begin();
          	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());
          			}
          		}
          	} finally {
          		tx.commit();
          	}
          }
          In other words you need to keep the persistence context open for the duration for the processing of the lazy loaded relationship to be resolved. I hope this helps in explaining the issue you are having.

          Comment


          • #6
            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

            Comment


            • #7
              Start to use OpenSessionInView or simply create a new method


              Code:
              for (Category category : categories) {
              	System.out.println("category: "+category.getName());
                      Set<Category> subCategories = categoryService.getSubCategories(category.getId())
              //	Set<Category> subCategories = category.getCategories(); LAZY //EXCEPTION HERE

              There is no other way how to do it because as you know the session is closed after each of your service method.

              Comment


              • #8
                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.

                Comment


                • #9
                  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.
                  Last edited by duardito; Sep 1st, 2009, 04:17 AM.

                  Comment


                  • #10
                    JPA Hibernate Spring Help!

                    Originally posted by duardito View Post
                    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...

                    Comment


                    • #11
                      Originally posted by logixplayer View Post
                      Perhaps what you are trying to say is that there should only be one overall transaction in the controller?
                      sorry if I didn't answer correctly before, I want to say something like this:

                      you have your controller:

                      Code:
                      class controller{
                      public ModelAndView onSubmit(Object command){
                      method A (propagation=Propagation.REQUIRED)
                      method B (propagation=Propagation.REQUIRED)
                      method C (parameter mehotd A, parameter method B)(propagation=Propagation.REQUIRED) 
                      // here LazyInitializationException because transaction of each method are closed, because
                      ModelAndView onSubmit(Object command) is not transactional
                      }
                      }
                      one solution to this would be something like this:
                      Code:
                      class DAO{
                      propagation=Propagation.REQUIRED
                      method TOCONTROLLER{
                      method A (propagation=Propagation.REQUIRED)
                      method B (propagation=Propagation.REQUIRED)
                      method C (parameter mehotd A, parameter method B)(propagation=Propagation.REQUIRED) 
                      //here you will not have exception because parent's method is transactional and required, so this is a transaction over other transactions included in sub_methods
                      }
                      }
                      IMHO.

                      what dou you think?

                      Comment


                      • #12
                        OpenEntityManagerInViewFilter LazyInitializationException HELP!!

                        Category controller is calling my category service.
                        Category Service is defined as such:

                        Code:
                        	@Transactional(propagation=Propagation.REQUIRED, readOnly=true)
                        	public List<Category> findByName(Object name, int[] rowStartIdxAndCount){
                        		 List<Category> result = iCategoryDAO.findByName(name,rowStartIdxAndCount);
                        		return result;
                        	}
                        So it is defined as
                        1)@Transactional
                        2)propagation=Propagation.REQUIRED
                        3)readOnly=true

                        Now, after I get back the List of Categories, I do this:

                        Code:
                        Set<Category> subCategories = category.getCategories();
                        and this is when I get the lazyLoadException.
                        Once again, my getCategories method is declared as LAZY:
                        Code:
                        	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "category")
                        	public Set<Category> getCategories() {
                        		return this.categories;
                        	}
                        Essentially this exception is happening outside of the first transaction (to get categories). I thought that by using OpenEntityManagerInViewFilter it can somehow re-open/re-attach that original session ....

                        web.xml:
                        Code:
                        	<filter>
                        	    <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
                        	    <filter-class>
                        	        org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
                        	    </filter-class>
                        	      <init-param>
                        			<param-name>singleSession</param-name>
                        			<param-value>false</param-value>
                        		</init-param>
                        	    
                        	</filter>
                        	
                        	<filter-mapping>
                        	    <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
                        	    <url-pattern>/*</url-pattern>
                        	</filter-mapping>
                        Any thoughts?

                        Comment


                        • #13
                          here is your problematic code:
                          Code:
                          		List<Category> categories = categoryService.findByName("Autos", null);//here session is opened
                          		//	should only be one category in actuality
                          		for (Category category : categories) {
                          			System.out.println("category: "+category.getName());//here session is closed
                          			
                          Set<Category> subCategories = category.getCategories(); LAZY EXCEPTION HERE because youe session is closed
                          to solve this you must decouple your dao code from controller, because as I said before your method is not transactional

                          Code:
                          public ModelAndView onSubmit(Object command)
                          so your option is to do a dao method doing all this;
                          Code:
                          @Transactional
                          class DAO{
                          
                          @Transactional(propagation=Propagation.REQUIRED, readOnly=true)
                          public Set returnSet(){
                          
                          List<Category> categories = categoryService.findByName("Autos", null);
                          		
                          	for (Category category : categories) {
                          			
                          Set<Category> subCategories = category.getCategories();
                          return subCategories ;
                          }
                          }
                          with this method you will be sure your returnSet() transaction will overwrite inner transactions, and then in your Controller class you can call this method without exception.

                          finally your controller class would be like:

                          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());
                          		
                          		ICategoryService categoryService = (ICategoryService)DataAccessServiceFactory.getBean("iCategoryService");
                          		ITopicService topicService = (ITopicService)DataAccessServiceFactory.getBean("iTopicService");
                          			
                          Set<Category> subCategories = returnSet(); //CODE CHANGED
                          			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());
                          					}
                          				}
                          			}
                          what do you think?

                          Comment


                          • #14
                            now I see other think, maybe you will have same problem with other code like this, because you are doing the same.
                            Code:
                            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();

                            Comment


                            • #15
                              JPA Hibernate Spring Help!

                              Appreciate the reply but that's really not the way I want to go.
                              The solution you posted is really not very flexible and it totally defeats the purpose of LazyLoading.

                              I would like to lazy load when I need to, which is why there is a OpenEntityManagerInViewFilter in the first place.


                              Note the following definition of 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.
                              The definition is perfect. It allows lazy loading in web views despite the original transactions already being completed.
                              But it's still not working. Some configuration missing somewhere!!!

                              Thoughts and solutions? Thanks!

                              Comment

                              Working...
                              X