Java Spring存储库Rest资源-未保存子对象的问题

Java Spring存储库Rest资源-未保存子对象的问题,java,spring,spring-data,spring-data-jpa,spring-data-rest,Java,Spring,Spring Data,Spring Data Jpa,Spring Data Rest,我一直在尝试使用SpringBoot实现RESTful接口,但遇到了一个问题 在发布以下JSON时,我得到一个org.hibernate.TransientObjectException异常(请参见下文),表明未保存子对象 在手动跟踪中,JSON似乎正确地呈现到域对象中,但当调用save()方法(SimpleJPepository)时,它不会尝试通过任何子对象向下递归。这是故意的吗?如果是这样,配置@RepositoryRestResource以保存子对象的正确方法是什么 我有一个最小的spri

我一直在尝试使用SpringBoot实现RESTful接口,但遇到了一个问题

在发布以下JSON时,我得到一个org.hibernate.TransientObjectException异常(请参见下文),表明未保存子对象

在手动跟踪中,JSON似乎正确地呈现到域对象中,但当调用save()方法(SimpleJPepository)时,它不会尝试通过任何子对象向下递归。这是故意的吗?如果是这样,配置@RepositoryRestResource以保存子对象的正确方法是什么

我有一个最小的spring.boot应用程序,如果它有助于诊断的话,我很乐意提供它

我一直在寻找一个有子对象(关系)的工作示例,但还没有找到。spring.io的例子对我来说非常有用,但我在扩展它时遇到了一些困难

代码片段如下所示:



它是使用以下命令发布的:

curl -i -X POST -H "Content-Type:application/json" --data @postdata.txt http://localhost:8080/samplegroup/

引发的异常如下所示:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: uk.ac.sanger.mig.samplegroup.domain.Sample
    at** org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:294)
    at org.hibernate.type.EntityType.getIdentifier(EntityType.java:510)
    at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:165)
    at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:899)
    at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1308)
    at org.hibernate.persister.collection.OneToManyPersister.recreate(OneToManyPersister.java:184)
    at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:67)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:453)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:345)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1218)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:421)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy67.save(Unknown Source)
    at org.springframework.data.rest.core.invoke.CrudRepositoryInvoker.invokeSave(CrudRepositoryInvoker.java:106)
    at org.springframework.data.rest.webmvc.RepositoryEntityController.createAndReturn(RepositoryEntityController.java:339)
    at org.springframework.data.rest.webmvc.RepositoryEntityController.postEntity(RepositoryEntityController.java:177)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1721)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1679)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
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);

}
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; // What the buisiness user prefers to call the sample.

    @Column(unique=true, nullable=false)
    private String wtsiUID;         // must be 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;
    }
}

RESTful存储库定义如下:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: uk.ac.sanger.mig.samplegroup.domain.Sample
    at** org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:294)
    at org.hibernate.type.EntityType.getIdentifier(EntityType.java:510)
    at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:165)
    at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:899)
    at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1308)
    at org.hibernate.persister.collection.OneToManyPersister.recreate(OneToManyPersister.java:184)
    at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:67)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:453)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:345)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1218)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:421)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy67.save(Unknown Source)
    at org.springframework.data.rest.core.invoke.CrudRepositoryInvoker.invokeSave(CrudRepositoryInvoker.java:106)
    at org.springframework.data.rest.webmvc.RepositoryEntityController.createAndReturn(RepositoryEntityController.java:339)
    at org.springframework.data.rest.webmvc.RepositoryEntityController.postEntity(RepositoryEntityController.java:177)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1721)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1679)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
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);

}
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; // What the buisiness user prefers to call the sample.

    @Column(unique=true, nullable=false)
    private String wtsiUID;         // must be 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;
    }
}
包uk.ac.sanger.mig.samplegroup.repository;
导入java.util.List;
导入org.springframework.data.repository.paging和sortingrepository;
导入org.springframework.data.repository.query.Param;
导入org.springframework.data.rest.core.annotation.RepositoryRestResource;
导入uk.ac.sanger.mig.samplegroup.domain.samplegroup;
@RepositoryRestResource(collectionResourceRel=“samplegroup”,path=“samplegroup”)
公共接口SampleGroupRepository扩展了分页和排序存储库{
列出findByName(@Param(“name”)字符串名);
列出findByCreator(@Param(“name”)字符串名称);
}

实体定义如下:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: uk.ac.sanger.mig.samplegroup.domain.Sample
    at** org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:294)
    at org.hibernate.type.EntityType.getIdentifier(EntityType.java:510)
    at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:165)
    at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:899)
    at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1308)
    at org.hibernate.persister.collection.OneToManyPersister.recreate(OneToManyPersister.java:184)
    at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:67)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:453)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:345)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1218)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:421)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy67.save(Unknown Source)
    at org.springframework.data.rest.core.invoke.CrudRepositoryInvoker.invokeSave(CrudRepositoryInvoker.java:106)
    at org.springframework.data.rest.webmvc.RepositoryEntityController.createAndReturn(RepositoryEntityController.java:339)
    at org.springframework.data.rest.webmvc.RepositoryEntityController.postEntity(RepositoryEntityController.java:177)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1721)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1679)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
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);

}
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; // What the buisiness user prefers to call the sample.

    @Column(unique=true, nullable=false)
    private String wtsiUID;         // must be 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;
    }
}
包uk.ac.sanger.mig.samplegroup.domain;
导入java.util.Date;
导入java.util.Set;
导入javax.persistence.Column;
导入javax.persistence.Entity;
导入javax.persistence.GeneratedValue;
导入javax.persistence.GenerationType;
导入javax.persistence.Id;
导入javax.persistence.JoinColumn;
导入javax.persistence.OneToMany;
导入javax.persistence.SequenceGenerator;
@实体
公共类抽样组{
//数据库主键只能使用。
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE,generator=“样本组顺序”)
@序列发生器(
name=“样本组顺序”,
sequenceName=“样本组顺序”,
allocationSize=1
)
私人长id;
@列(unique=true,nullable=false)
私有字符串名称;
私有字符串描述;
私有字符串代码;
私有字符串创建者;
私人日期创建日期;
私人日期最后修改日期;
@独身癖
@JoinColumn(name=“SAMPLE_FK”)
私人样本;
公共样本组(){}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共字符串getCreator(){
回归创造者;
}
公共void集合创建者(字符串创建者){
this.creator=创建者;
}
公共日期getCreatedDate(){
返回createdDate;
}
public void setCreatedDate(日期createdDate){
this.createdDate=createdDate;
}
公共日期getLastModifiedDate(){
返回最后修改日期;
}
公共无效setLastModifiedDate(日期lastModifiedDate){
this.lastModifiedDate=lastModifiedDate;
}
公共集getSamples(){
返回样品;
}
公共无效集合样本(集合样本){
这个。样本=样本;
}
公共字符串getDescription(){
返回说明;
}
公共void集合描述(字符串描述){
this.description=描述;
}
公共字符串getProjectCode(){
返回项目代码;
}
公共无效setProjectCode(字符串projectCode){
this.projectCode=projectCode;
}
@凌驾
公共字符串toString(){
返回“SampleGroup[id=“+id+”,name=“+name+”,description=”
+description+”,projectCode=“+projectCode+”,creator=”
+creator+”,createdDate=“+createdDate
+,lastModifiedDate=“+lastModifiedDate+”,示例=“
+样本+“]”;
}
@凌驾
公共int hashCode(){
最终整数素数=31;
int结果=1;
result=prime*result+((name==null)?0:name.hashCode();
结果=素数*结果
+((projectCode==null)?0:projectCode.hashCode());
返回结果;
}
@凌驾
公共布尔等于(对象obj){
if(this==obj)
返回true;
if(obj==null)
返回false;
如果(getClass()!=obj.getClass())
返回false;
样本组其他=(样本组)obj;
if(name==null){
if(other.name!=null)
返回false;
}如果(!name.equals(other.name))
返回false;
if(projectCode==null){
if(other.projectCode!=null)
返回false;
}如果(!projectCode.equals(other.projectCode))
返回false;
返回true;
}
}
包uk.ac.sanger.mig.samplegroup.domain;
导入java.util.Set;
导入javax.persistence.Column;
导入javax.persistence.ElementCollection;
导入javax.persistence.Entity;
导入javax.persistence.GeneratedValue;
导入javax.persistence.GenerationType;
导入javax.persistence.Id;
导入javax.persistence.SequenceGenerator;
@实体
公共类样本{
//数据库主键只能使用。
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE,generator=“示例顺序”)
@序列发生器(
name=“SAMPLE_SEQ”,
sequenceName=“样本顺序”,
allocationSize=1
)
私人长id;