java - Spring Repository Rest Resource - issue not saving sub objects -


i have been trying restful interface going spring boot have hit problem.

when post'ing following json org.hibernate.transientobjectexception exception (please see below) indicates sub-object not being saved.

on hand tracing appears json correctly rendered domain objects when save() method (simplejparepository) called doesn't attempt recurse down through sub-objects. intentional? if so, correct approach configuring @repositoryrestresource such save sub-objects?

i have minimal spring.boot application happily provide if diagnosis.

i have been looking around working example has sub-object (relation) haven't found 1 yet. spring.io example great getting me going have become bit stuck expanding on it.

code snippets follow below:


json being posted:  {   "name" : "test sample group",   "description" : null,   "projectcode" : null,   "creator" : "user001",   "createddate" : 1395130128971,   "lastmodifieddate" : 1395130128971,   "samples" : [ {     "userpreferredid" : "s00012223434",     "wtsiuid" : "99997853483845",     "synonyms" : [ "abc12345", "humgen-0011232233", "1200088132734888234" ]   }, {     "userpreferredid" : "s000634734588",     "wtsiuid" : "34583934085358",     "synonyms" : [ "4875345993599934", "humgen-004537682", "abc674534" ]   } ] } 

which posted using following command:

curl -i -x post -h "content-type:application/json" --data @postdata.txt http://localhost:8080/samplegroup/ 

the exception thrown follows:

org.hibernate.transientobjectexception: object references unsaved transient instance - save transient instance before flushing: uk.ac.sanger.mig.samplegroup.domain.sample     at** org.hibernate.engine.internal.foreignkeys.getentityidentifierifnotunsaved(foreignkeys.java:294)     @ org.hibernate.type.entitytype.getidentifier(entitytype.java:510)     @ org.hibernate.type.manytoonetype.nullsafeset(manytoonetype.java:165)     @ org.hibernate.persister.collection.abstractcollectionpersister.writeelement(abstractcollectionpersister.java:899)     @ org.hibernate.persister.collection.abstractcollectionpersister.recreate(abstractcollectionpersister.java:1308)     @ org.hibernate.persister.collection.onetomanypersister.recreate(onetomanypersister.java:184)     @ org.hibernate.action.internal.collectionrecreateaction.execute(collectionrecreateaction.java:67)     @ org.hibernate.engine.spi.actionqueue.executeactions(actionqueue.java:453)     @ org.hibernate.engine.spi.actionqueue.executeactions(actionqueue.java:345)     @ org.hibernate.event.internal.abstractflushingeventlistener.performexecutions(abstractflushingeventlistener.java:350)     @ org.hibernate.event.internal.defaultflusheventlistener.onflush(defaultflusheventlistener.java:56)     @ org.hibernate.internal.sessionimpl.flush(sessionimpl.java:1218)     @ org.hibernate.internal.sessionimpl.managedflush(sessionimpl.java:421)     @ org.hibernate.engine.transaction.internal.jdbc.jdbctransaction.beforetransactioncommit(jdbctransaction.java:101)     @ org.hibernate.engine.transaction.spi.abstracttransactionimpl.commit(abstracttransactionimpl.java:177)     @ org.hibernate.jpa.internal.transactionimpl.commit(transactionimpl.java:77)     @ org.springframework.orm.jpa.jpatransactionmanager.docommit(jpatransactionmanager.java:515)     @ org.springframework.transaction.support.abstractplatformtransactionmanager.processcommit(abstractplatformtransactionmanager.java:757)     @ org.springframework.transaction.support.abstractplatformtransactionmanager.commit(abstractplatformtransactionmanager.java:726)     @ org.springframework.transaction.interceptor.transactionaspectsupport.committransactionafterreturning(transactionaspectsupport.java:478)     @ org.springframework.transaction.interceptor.transactionaspectsupport.invokewithintransaction(transactionaspectsupport.java:272)     @ org.springframework.transaction.interceptor.transactioninterceptor.invoke(transactioninterceptor.java:95)     @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:179)     @ org.springframework.dao.support.persistenceexceptiontranslationinterceptor.invoke(persistenceexceptiontranslationinterceptor.java:136)     @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:179)     @ org.springframework.data.jpa.repository.support.lockmoderepositorypostprocessor$lockmodepopulatingmethodintercceptor.invoke(lockmoderepositorypostprocessor.java:92)     @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:179)     @ org.springframework.aop.interceptor.exposeinvocationinterceptor.invoke(exposeinvocationinterceptor.java:92)     @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:179)     @ org.springframework.aop.framework.jdkdynamicaopproxy.invoke(jdkdynamicaopproxy.java:207)     @ com.sun.proxy.$proxy67.save(unknown source)     @ org.springframework.data.rest.core.invoke.crudrepositoryinvoker.invokesave(crudrepositoryinvoker.java:106)     @ org.springframework.data.rest.webmvc.repositoryentitycontroller.createandreturn(repositoryentitycontroller.java:339)     @ org.springframework.data.rest.webmvc.repositoryentitycontroller.postentity(repositoryentitycontroller.java:177)     @ sun.reflect.nativemethodaccessorimpl.invoke0(native method)     @ sun.reflect.nativemethodaccessorimpl.invoke(nativemethodaccessorimpl.java:57)     @ sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl.java:43)     @ java.lang.reflect.method.invoke(method.java:606)     @ org.springframework.web.method.support.invocablehandlermethod.invoke(invocablehandlermethod.java:215)     @ org.springframework.web.method.support.invocablehandlermethod.invokeforrequest(invocablehandlermethod.java:132)     @ org.springframework.web.servlet.mvc.method.annotation.servletinvocablehandlermethod.invokeandhandle(servletinvocablehandlermethod.java:104)     @ org.springframework.web.servlet.mvc.method.annotation.requestmappinghandleradapter.invokehandlemethod(requestmappinghandleradapter.java:749)     @ org.springframework.web.servlet.mvc.method.annotation.requestmappinghandleradapter.handleinternal(requestmappinghandleradapter.java:690)     @ org.springframework.web.servlet.mvc.method.abstracthandlermethodadapter.handle(abstracthandlermethodadapter.java:83)     @ org.springframework.web.servlet.dispatcherservlet.dodispatch(dispatcherservlet.java:945)     @ org.springframework.web.servlet.dispatcherservlet.doservice(dispatcherservlet.java:876)     @ org.springframework.web.servlet.frameworkservlet.processrequest(frameworkservlet.java:961)     @ org.springframework.web.servlet.frameworkservlet.dopost(frameworkservlet.java:863)     @ javax.servlet.http.httpservlet.service(httpservlet.java:646)     @ org.springframework.web.servlet.frameworkservlet.service(frameworkservlet.java:837)     @ javax.servlet.http.httpservlet.service(httpservlet.java:727)     @ org.apache.catalina.core.applicationfilterchain.internaldofilter(applicationfilterchain.java:303)     @ org.apache.catalina.core.applicationfilterchain.dofilter(applicationfilterchain.java:208)     @ org.springframework.web.filter.hiddenhttpmethodfilter.dofilterinternal(hiddenhttpmethodfilter.java:77)     @ org.springframework.web.filter.onceperrequestfilter.dofilter(onceperrequestfilter.java:108)     @ org.apache.catalina.core.applicationfilterchain.internaldofilter(applicationfilterchain.java:241)     @ org.apache.catalina.core.applicationfilterchain.dofilter(applicationfilterchain.java:208)     @ org.apache.catalina.core.standardwrappervalve.invoke(standardwrappervalve.java:220)     @ org.apache.catalina.core.standardcontextvalve.invoke(standardcontextvalve.java:122)     @ org.apache.catalina.authenticator.authenticatorbase.invoke(authenticatorbase.java:501)     @ org.apache.catalina.valves.remoteipvalve.invoke(remoteipvalve.java:683)     @ org.apache.catalina.core.standardhostvalve.invoke(standardhostvalve.java:170)     @ org.apache.catalina.valves.errorreportvalve.invoke(errorreportvalve.java:98)     @ org.apache.catalina.core.standardenginevalve.invoke(standardenginevalve.java:116)     @ org.apache.catalina.connector.coyoteadapter.service(coyoteadapter.java:408)     @ org.apache.coyote.http11.abstracthttp11processor.process(abstracthttp11processor.java:1040)     @ org.apache.coyote.abstractprotocol$abstractconnectionhandler.process(abstractprotocol.java:607)     @ org.apache.tomcat.util.net.nioendpoint$socketprocessor.dorun(nioendpoint.java:1721)     @ org.apache.tomcat.util.net.nioendpoint$socketprocessor.run(nioendpoint.java:1679)     @ java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1145)     @ java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:615)     @ java.lang.thread.run(thread.java:744) 

the restful repository definition follows:

package uk.ac.sanger.mig.samplegroup.repository;  import java.util.list;  import org.springframework.data.repository.pagingandsortingrepository; import org.springframework.data.repository.query.param; import org.springframework.data.rest.core.annotation.repositoryrestresource;  import uk.ac.sanger.mig.samplegroup.domain.samplegroup;  @repositoryrestresource(collectionresourcerel = "samplegroup", path = "samplegroup") public interface samplegrouprepository extends pagingandsortingrepository<samplegroup, long> {      list<samplegroup> findbyname(@param("name") string name);     list<samplegroup> findbycreator(@param("name") string name);  } 

entity definitions follows:

package uk.ac.sanger.mig.samplegroup.domain;  import java.util.date; import java.util.set;  import javax.persistence.column; import javax.persistence.entity; import javax.persistence.generatedvalue; import javax.persistence.generationtype; import javax.persistence.id; import javax.persistence.joincolumn; import javax.persistence.onetomany; import javax.persistence.sequencegenerator;   @entity public class samplegroup {      // database primary key use only.     @id     @generatedvalue(strategy=generationtype.sequence, generator="sample_group_seq")     @sequencegenerator(             name="sample_group_seq",             sequencename="sample_group_seq",             allocationsize=1     )     private long id;      @column(unique=true, nullable=false)     private string name;      private string description;      private string projectcode;      private string creator;     private date createddate;     private date lastmodifieddate;      @onetomany     @joincolumn(name="sample_fk")     private set<sample> samples;      public samplegroup() {}      public string getname() {         return name;     }      public void setname(string name) {         this.name = name;     }      public string getcreator() {         return creator;     }      public void setcreator(string creator) {         this.creator = creator;     }      public date getcreateddate() {         return createddate;     }      public void setcreateddate(date createddate) {         this.createddate = createddate;     }      public date getlastmodifieddate() {         return lastmodifieddate;     }      public void setlastmodifieddate(date lastmodifieddate) {         this.lastmodifieddate = lastmodifieddate;     }      public set<sample> getsamples() {         return samples;     }      public void setsamples(set<sample> samples) {         this.samples = samples;     }       public string getdescription() {         return description;     }      public void setdescription(string description) {         this.description = description;     }      public string getprojectcode() {         return projectcode;     }      public void setprojectcode(string projectcode) {         this.projectcode = projectcode;     }      @override     public string tostring() {         return "samplegroup [id=" + id + ", name=" + name + ", description="                 + description + ", projectcode=" + projectcode + ", creator="                 + creator + ", createddate=" + createddate                 + ", lastmodifieddate=" + lastmodifieddate + ", samples="                 + samples + "]";     }      @override     public int hashcode() {         final int prime = 31;         int result = 1;         result = prime * result + ((name == null) ? 0 : name.hashcode());         result = prime * result                 + ((projectcode == null) ? 0 : projectcode.hashcode());         return result;     }      @override     public boolean equals(object obj) {         if (this == obj)             return true;         if (obj == null)             return false;         if (getclass() != obj.getclass())             return false;         samplegroup other = (samplegroup) obj;         if (name == null) {             if (other.name != null)                 return false;         } else if (!name.equals(other.name))             return false;         if (projectcode == null) {             if (other.projectcode != null)                 return false;         } else if (!projectcode.equals(other.projectcode))             return false;         return true;     } }  package uk.ac.sanger.mig.samplegroup.domain;  import java.util.set;  import javax.persistence.column; import javax.persistence.elementcollection; import javax.persistence.entity; import javax.persistence.generatedvalue; import javax.persistence.generationtype; import javax.persistence.id; import javax.persistence.sequencegenerator;  @entity public class sample {      // database primary key use only.     @id     @generatedvalue(strategy=generationtype.sequence, generator="sample_seq")     @sequencegenerator(             name="sample_seq",             sequencename="sample_seq",             allocationsize=1         )     private long id;      private string userpreferredid; // buisiness user prefers call sample.      @column(unique=true, nullable=false)     private string wtsiuid;         // must unique within wtsi (primary key)      @elementcollection     private set<string> synonyms;      public sample() {}      public string getuserpreferredid() {         return userpreferredid;     }      public void setuserpreferredid(string userpreferredid) {         this.userpreferredid = userpreferredid;     }      public string getwtsiuid() {         return wtsiuid;     }      public void setwtsiuid(string wtsiuid) {         this.wtsiuid = wtsiuid;     }      public set<string> getsynonyms() {         return synonyms;     }      public void setsynonyms(set<string> synonyms) {         this.synonyms = synonyms;     }      @override     public string tostring() {         return "sample [id=" + id + ", userpreferredid=" + userpreferredid                 + ", wtsiuid=" + wtsiuid + ", synonyms=" + synonyms + "]";     }      @override     public int hashcode() {         final int prime = 31;         int result = 1;         result = prime * result + ((wtsiuid == null) ? 0 : wtsiuid.hashcode());         return result;     }      @override     public boolean equals(object obj) {         if (this == obj)             return true;         if (obj == null)             return false;         if (getclass() != obj.getclass())             return false;         sample other = (sample) obj;         if (wtsiuid == null) {             if (other.wtsiuid != null)                 return false;         } else if (!wtsiuid.equals(other.wtsiuid))             return false;         return true;     } } 

the issue when saving samplegroup, samples inside set not managed hibernate. 1 solution make following change:

@onetomany(cascade={cascadetype.persist, cascadetype.merge}) @joincolumn(name="sample_fk") private set<sample> samples; 

Comments

Popular posts from this blog

windows - Single EXE to Install Python Standalone Executable for Easy Distribution -

c# - Access objects in UserControl from MainWindow in WPF -

javascript - How to name a jQuery function to make a browser's back button work? -