Announcement Announcement Module
No announcement yet.
InvalidDataAccessApiUsageException Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • InvalidDataAccessApiUsageException

    Hi there

    I am making a webapplication using spring and hibernate. I am using Hibernate's "lazy loading" of some data objects as it gives a performance boost, and therefore I am using one of Spring's interceptors for holding a hibernate session for the duration of a request. This is required for lazy loading.

    I have the interceptor configured as follows:

    <property name="interceptors">
    <ref bean="openSessionInViewInterceptor"/>

    But I get a problem when I try to create a new data object. In my formBackingObject method I create a new (empty) data object for supplying to the JSP - which then displays empty fields for the user to input new data. But this leads to the following exception. Can someone explain why, and how I can get around this? I assume it is something to do with the Hibernate session still being open, and Hibernate is trying to synchronise an "empty" object with the database...?

    org.springframework.dao.InvalidDataAccessApiUsageE xception: object references an unsaved transient instance - save the transient instance before flushing: dk.ciber.danbro.facility.impl.DefaultConstructionN ode
    org.springframework.orm.hibernate.SessionFactoryUt ils.convertHibernateAccessException(SessionFactory
    org.springframework.orm.hibernate.HibernateAccesso r.convertHibernateAccessException(HibernateAccesso
    org.springframework.orm.hibernate.HibernateTemplat e.execute(
    org.springframework.orm.hibernate.HibernateTemplat e.executeFind(
    org.springframework.orm.hibernate.HibernateTemplat e.find(
    dk.ciber.danbro.catalogue.impl.DefaultCatalogueMan ager.getCatalogueNodes(DefaultCatalogueManager.jav a:51)
    dk.ciber.danbro.facility.web.SimpleFacilityFormCon troller.generateDataLists(SimpleFacilityFormContro
    dk.ciber.danbro.facility.web.SimpleFacilityFormCon troller.referenceData(SimpleFacilityFormController .java:119)
    org.springframework.web.servlet.mvc.SimpleFormCont roller.referenceData( )
    org.springframework.web.servlet.mvc.AbstractFormCo ntroller.showForm(
    org.springframework.web.servlet.mvc.AbstractFormCo ntroller.showForm(
    org.springframework.web.servlet.mvc.SimpleFormCont roller.showForm(
    org.springframework.web.servlet.mvc.AbstractFormCo ntroller.showNewForm( 84)
    org.springframework.web.servlet.mvc.AbstractFormCo ntroller.handleRequestInternal(AbstractFormControl
    org.springframework.web.servlet.mvc.AbstractContro ller.handleRequest(
    org.springframework.web.servlet.mvc.SimpleControll erHandlerAdapter.handle(SimpleControllerHandlerAda
    org.springframework.web.servlet.DispatcherServlet. doService(
    org.springframework.web.servlet.FrameworkServlet.s ervice(
    javax.servlet.http.HttpServlet.service(HttpServlet .java:856)


  • #2
    Well, you're confusing Hibernate somehow here. This only looks to be thrown from a method in Hibernate called getEntityIdentifierIfNotUnsaved(), and as far as I can tell, in a query, you're using an entity (this would be your empty object) either directly or indirectly (I would presume indirectly), which as far as Hibernate can tell is unsaved.

    I think Hibernate wants to flush before doing the query, and at that point it's not happy about this instance.

    The point with the OpenSessionInView filter is that you have one live session the whole request (unless yo turn off the singlesession mode and use it purely to delay closing), so you have to be careful what you do with persistent objects even in your view layer, as they are live.

    Additionally, you have no transaction as far as I can tell by the stacktrace. You should really be using transactions.

    One strategy would be to go to the session in view interceptor with the singleSession flag turned off. Then all the interceptor would do would be deferring closing of sessions so lazy relationships could be traversed, but you would still get a new session on each call down into your service layer (assuming you set up proper transactions with HibernateTransactionManager).


    • #3
      Thanks for the help.