简体   繁体   中英

Hibernate unable to save child objects using cascade all

I have the following two classes. Class 'Type' has a an object of class 'Content'. I want to save all referenced objects of class 'Type' by using the hibernate.save() method. I have specified the cascade type as ALL in class 'Content'.

Following is the error i face: object references an unsaved transient instance - save the transient instance before flushing.

Can someone please help me identify what the problem is?

public class Type {
    @OneToOne
    @JoinColumn(name = "content_id")
    private Content content;
    }

    public class Content {
        @OneToOne(mappedBy = "content", cascade = CascadeType.ALL)
        private Type type;
    }

    public class Test {
        public void createType() {
            Type type = new Type();
            Content content = someMethodToGetContent();
            type.setContent(content);
            save(type); 
        }

        public void save(Object domainObj) {
            getEntityManager().persist(domainObj);
            getEntityManager().flush();
        }
    }

Stacktrace:

Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: .content -> .Content at org.hibernate.engine.CascadingAction$9.noCascade(CascadingAction.java:387) at org.hibernate.engine.Cascade.cascade(Cascade.java:172) at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154) at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145) at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216) at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:795) ... 27 more org.springframework.transaction.TransactionSystemException: Could not commit JPA tr ansaction; nested exception is javax.persistence.RollbackException: Transacti on marked as rollbackOnly at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:526) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.in voke(JdkDynamicAopProxy.java:213) at com.sun.proxy.$Proxy29.persist(Unknown Source) Caused by: javax.persistence.RollbackException: Transaction marked as rollbackOnly at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:73) at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517) ... 12 more

Please change your createType() as below.

public void createType() {
Type type = new Type();
Content content = someMethodToGetContent();
content.setType();
type.setContent(content);
save(type); 
}

Hibernate unable to save child objects using cascade all

The reason why this does not work has to do with the way you're trying to persit the entities.

  • Let us see what the following code is doing:

     Type type = new Type(); Content content = someMethodToGetContent(); type.setContent(content); save(type); 

You are telling the persistence provider you want to save type by calling save(type) and expecting content should also be saved to the database. But in the entity Type the OneToOne annotation is does not contain the PERSIST cascade option. So you have to tell the persistence provider to to pesist an instance of Content when an instance of Type is persisted by changing your OneToOne annotation as follows:

@OneToOne(cascade=CascadeType.PERSIST)    // modified
@JoinColumn(name = "content_id")
private Content content;

And because you defined to entities to have bi-directional relationship you should wire them as follows correctly:

Type type = new Type();
Content content = someMethodToGetContent();
content.setType(type);                       // modified
type.setContent(content);
save(type); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM