Announcement Announcement Module
No announcement yet.
OpenSessionInViewInterceptor and Hibernate lazy-loading Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • OpenSessionInViewInterceptor and Hibernate lazy-loading


    I am trying to use lazy-loading in Hibernate, and reading through the forums suggest that I should use OpenSessionInViewInterceptor or OpenSessionInViewFilter. I've got everything (SELECT, INSERT) to work perfectly... until I came to DELETE.

    Whenever I delete (after inserting and/or selecting), I was greeted with the following:

    org.springframework.orm.hibernate.HibernateSystemException: Illegal attempt to associate a collection with two open sessions; nested exception is net.sf.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
    I know that the code work when I change my app to non-lazy-loading in Hibernate and take out the OpenSessionInViewInterceptor, so at least all the basic structure are correct. It's just damn slow withing lazy-loading :roll:

    So anyway, here're the goods:

    in the spring-servlet.xml:
    	<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
    		<property name="sessionFactory">
    			<ref local="repositorySessionFactory"/>
            <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    		<property name="interceptors">
    				<ref bean="openSessionInViewInterceptor"/>
    		<property name="mappings">
    				<prop key="/workspace.view">springController</prop>
    	<bean name="openSessionInViewInterceptor" class="">
    		<property name="sessionFactory">
    			<ref local="repositorySessionFactory"/>
    		<property name="singleSession">
    My hibernate mapping xml:
    	<class name="Book" table="BOOK">
    		<id name="id" column="BOOK_ID" type="long">
    			<generator class="increment"/>
    		<set name="PageSet" inverse="true" cascade="all-delete-orphan" lazy="true">
    			<key column="PAGE_ID"/>
    			<one-to-many class="Page"/>
    Again since my code works when not using lazy, I know they work and I won't bother posting the Hibernate code here. Suffice to say I use getHibernateTemplate() for all operations.

    That's it, unless I forgot to post something. Did I miss something when I setup the OpenSessionInViewInterceptor? Should I have used OpenSessionInViewFilter? I read that they do the same thing so it shouldn't matter.

    Any help would be greatly appreciated!


  • #2

    It would help if you put the exception message in Google :wink: .

    This is what I came up with:

    Rgds, Ales


    • #3
      Google?! Why would I search Google when I have the Spring forum? :wink:

      Seriously, thanks for the link. I did search Google but perhaps my keywords were not there or I simply missed it.

      After reading the thread, it seems that my hope of having a "clean" design/implementation of Hibernate and Spring is not to be... by "clean" I mean

      (1) just letting Spring deal with the Hibernate sessions (i.e. OpenSessionInView) and

      (2) let Hibernate deal with the queries (i.e. with just the maps, Java classes and of course, lazy loading) without the need to deal with HSQL (I am talking about simple SELECT and DELETE of a graph of objects here, not crazy 10-page SQL), or off-loading to a different layer to handle the session

      I mean, that's the point of "outsourcing" the plumbing to Spring and Anything-Data to Hibernate, so I can focus on the core project, right?

      I just re-read what I wrote and it didn't come out quite the way I intended, but it does capture my sentiment. I love both frameworks and have been constantly impressed by the designs - which led me to believe that there's got to be an elegant solution to the mundane secnario I am dealing with right now.

      How do other people approach this problem? Would using iBatis or plain old JDO be "cleaner"? Any ideas?



      • #4
        Hi Paul,

        I ran into precisely the same problem.
        My solution can be found

        Basically, I ended up getting rid of OpenSessionInView, which was (to my surprise) quite painless - it simply involved touching the collections of certain objects in the service layer (either when first loading them or later, as required). As was pointed out to me, OpenSessionInView is not really meant to replace transactions - it is simply meant to allow you to lazy load collections in the view layer.

        Now I can still let Hibernate do the data access, I can still use lazy collection loading, and I can still pass my domain objects to all layers (and most specifically for UI binding). Basically I'm performing one transaction to load the object, (optionally) one transaction to reconnect it or one of its children to the DB and touch collections, and a final transaction to update it.

        Your other option, if you're hell bent on keeping OpenSessionInView, is to wrap a transaction around the SimpleFormController's handleRequest. This is quite easy to implement, but it puts transactions into the UI layer and makes testing your domain objects outside of the UI framework problematic (you need to start transactionalizing portions of your tests as well, which is a mess).

        Hopefully this helps.

        Best regards,
        Last edited by robyn; May 14th, 2006, 04:44 PM.