-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Bidirectional one-to-many TransientObjectException
PostPosted: Wed Apr 01, 2009 7:01 pm 
Newbie

Joined: Fri Jan 23, 2009 8:01 pm
Posts: 13
Greetings,

I'm still fairly new and using Hibernate 3 w/ Spring 2. I have a parent object (Title) that references some collections of child objects, in this case some language specific title data (TitleLanguageData) and my form is creating the parent and the child objects without issue. They link together and validate as expected. In fact, if I edit an existing parent with children it saves everything fine. My problem occurs when I try and add a new parent/child combination at the same time, I'm assuming because there is nothing in the DB referencing them yet.

Essentially I'm trying to add the parent and children but if I store the parent first, it fails when it gets to the collections because they haven't been linked to the parents ID (the parent hasn't been added so it doesn't have an id). I've tried vice-versa but that doesn't work either (or make sense anyhow).

In my mind the only way to do this would be to unlink the child collections from the parent, save the parent, then re-link the children to the parent and save the children but that seems like a lot of extra work and I'm sure hibernate is smarter than that.

Here are my mappings to give context, am I doing something fundamentally wrong?? I can provide anything else you need. THANKS!

Code:
<class name="ovm.central.Title" table="title">
   <id name="id" column="title_pk">
      <generator class="sequence">
         <param name="sequence">title_seq</param>
      </generator>
   </id>
   <many-to-one name="assetBillingState" column="asset_billing_state_fk" class="ovm.central.AssetBillingState"/>
   <property name="adult" column="adult"/>
   <property name="director" column="director"/>
   <property name="actors" column="actors"/>
   <set name="titleLanguageDataInternal" table="title_lang_data" inverse="true">
      <key column="title_fk"/>
      <one-to-many class="ovm.central.TitleLanguageData"/>
   </set>
   <set name="titleImagesInternal" table="title_image" inverse="true">
      <key column="title_fk"/>
      <one-to-many class="ovm.central.TitleImage"/>
   </set>
   <set name="categoriesInternal" table="title_x_category">
      <key column="title_fk"/>
      <many-to-many column="category_fk" class="ovm.central.Category"/>
   </set>
   <set name="instancesInternal" table="instance" inverse="true">
      <key column="title_fk"/>
      <one-to-many class="ovm.central.Instance"/>
   </set>
</class>

<class name="ovm.central.TitleLanguageData" table="title_lang_data">
   <id name="id" column="title_lang_data_pk">
      <generator class="sequence">
         <param name="sequence">title_lang_data_seq</param>
      </generator>
   </id>
   <many-to-one name="title" column="title_fk" insert="false" update="false" not-null="true" class="ovm.central.Title"/>
   <many-to-one name="language" column="language_fk" not-null="true" class="ovm.central.Language"/>
   <property name="titleString" column="title"/>
   <property name="synopsisString" column="synopsis"/>
</class>


In my controller:

Code:

.... // this is how I create/delete children and link them together

if(formAction != null && formAction.equals("addLang")) {
   
   log.info("Linking new title language data field to title: LangId = " + request.getParameter("languages"));

   TitleLanguageData tld = new TitleLanguageData();
   tld.setLanguage((Language)core.loadObject(Language.class, new Integer(request.getParameter("languages"))));
   tld.setTitle(title);
   title.addTitleLanguageData(tld);
   
} else if(formAction != null && formAction.equals("delLang")) {

   String deleteLangId = request.getParameter("deleteLangId");
   
   log.info("Deleting title language data with language id: " + deleteLangId);
   
   for (int i = 0; i < title.getTitleLanguageDataCount(); i++) {
      if(title.getTitleLanguageData().get(i).getLanguage().getId().toString().equals(deleteLangId)) {
         this.core.deleteObject(TitleLanguageData.class, title.getTitleLanguageData().get(i));
         title.clearTitleLanguageData(title.getTitleLanguageData().get(i));
      }
   }
}

.... // the actual hibernate calls that follow validation

log.info("Storing title.");

this.core.storeObject(title.getClass(), title);

for (int i = 0; i < title.getTitleLanguageData().size(); i++) {
   this.core.storeObject(title.getTitleLanguageData().get(i).getClass(),
         title.getTitleLanguageData().get(i));
}


Hibernate version: 3.x

Code between sessionFactory.openSession() and session.close():
sessionFactory.getCurrentSession().merge(persistanceClass.cast(obj));

Full stack trace of any exception that occurs:
2009-04-01 14:22:56,322 ERROR [ovm.central.hibernate.HibernateCore] - <Error storing object Title>
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: ovm.central.TitleLanguageData
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:397)
at org.hibernate.type.EntityType.replace(EntityType.java:253)
at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:485)
at org.hibernate.type.CollectionType.replace(CollectionType.java:552)
at org.hibernate.type.AbstractType.replace(AbstractType.java:153)
at org.hibernate.type.TypeFactory.replaceAssociations(TypeFactory.java:564)
at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:366)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:195)
at org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener.entityIsTransient(IdTransferringMergeEventListener.java:58)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
at ovm.central.hibernate.HibernateCore.storeObject(HibernateCore.java:391)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy34.storeObject(Unknown Source)
at ovm.central.web.TitleAddForm.processSubmit(TitleAddForm.java:146)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:305)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:131)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:308)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:295)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:808)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:523)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:463)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:75)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:595)

Hibernate: insert into title (asset_billing_state_fk, adult, length, box_office, status, director, producer, actors, macrovision, title_pk) values (?, ?, ?,
?, ?, ?, ?, ?, ?, ?)
2009-04-01 14:22:56,331 ERROR [ovm.central.hibernate.HibernateCore] - <Error storing object TitleLanguageData>
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: ovm.central.Title
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:397)
at org.hibernate.type.EntityType.replace(EntityType.java:253)
at org.hibernate.type.AbstractType.replace(AbstractType.java:153)
at org.hibernate.type.TypeFactory.replace(TypeFactory.java:515)
at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:377)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:179)
at org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener.entityIsTransient(IdTransferringMergeEventListener.java:58)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
at ovm.central.hibernate.HibernateCore.storeObject(HibernateCore.java:391)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy34.storeObject(Unknown Source)
at ovm.central.web.TitleAddForm.processSubmit(TitleAddForm.java:149)
....

Name and version of the database you are using: Postgres 8.3


Top
 Profile  
 
 Post subject: Fixed!
PostPosted: Thu Apr 02, 2009 8:02 pm 
Newbie

Joined: Fri Jan 23, 2009 8:01 pm
Posts: 13
So I talked myself through it... I just changed my controller code to backup the collections, clear the dependancies on my parent object, save the parent, then save the children and all the references stay in place!

Hopefully this helps someone.

Code:
         log.info("Storing title.");
         
         List<TitleLanguageData> tld = title.getTitleLanguageData();
         List<TitleImage> posters = title.getTitleImages();
         
         title.clearTitleLanguageData();
         title.clearTitleImages();
         
         this.core.storeObject(title.getClass(), title);
         
         for (int i = 0; i < tld.size(); i++)
            this.core.storeObject(tld.get(i).getClass(), tld.get(i));
         
         for (int i = 0; i < posters.size(); i++)
            this.core.storeObject(posters.get(i).getClass(), posters.get(i));


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.