Reputation: 560
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 transaction; 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.invoke(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
Upvotes: 0
Views: 4351
Reputation: 3309
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);
Upvotes: 2
Reputation: 490
Please change your createType() as below.
public void createType() {
Type type = new Type();
Content content = someMethodToGetContent();
content.setType();
type.setContent(content);
save(type);
}
Upvotes: 1