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