Sleep mode - From one to many relationships and an orphan frame

I have a basic parent / child relationship, as in chapter 21 of the Hibernate reference book.
Cascade - only from child to parent (keep the cascade only because I do not want to remove the parent if I delete the child).
When I add a child to the parent element and I save it, I have a TransientObjectException ...

@Entity public class Parent implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @OneToMany(mappedBy = "parent", orphanRemoval = true) private List<Child> childs; public List<Child> getChilds() { return childs; } public void setChilds(List<Child> childs) { this.childs = childs; } public void addChild(Child child) { if (childs == null) childs = new ArrayList<Child>(); if (childs.add(child)) child.setParent(this); } public Long getId() { return id; } public void setId(Long id) { this.id = id; } } @Entity public class Child implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @ManyToOne(optional = false) @Cascade( { PERSIST, MERGE, REFRESH, SAVE_UPDATE, REPLICATE, LOCK, DETACH }) private Parent parent; public Parent getParent() { return parent; } public void setParent(Parent parent) { this.parent = parent; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } } @Test public void test() { Parent parent = new Parent(); Child child = new Child(); parent.addChild(child); genericDao.saveOrUpdate(child); } 

But on saveOrUpdate, I have this exception:

 org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Child at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:244) at org.hibernate.collection.AbstractPersistentCollection.getOrphans(AbstractPersistentCollection.java:911) at org.hibernate.collection.PersistentBag.getOrphans(PersistentBag.java:143) at org.hibernate.engine.CollectionEntry.getOrphans(CollectionEntry.java:373) at org.hibernate.engine.Cascade.deleteOrphans(Cascade.java:471) at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:455) at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362) at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338) at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204) at org.hibernate.engine.Cascade.cascade(Cascade.java:161) at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:476) at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:354) at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204) at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93) at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677) at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669) at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:252) at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392) at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335) at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204) at org.hibernate.engine.Cascade.cascade(Cascade.java:161) at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:451) at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288) at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204) at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93) at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677) at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669) at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:665) 

I really don't understand, because saving a child should save a parent through a cascade ... Any ideas?

UPDATE 1
The problem seems to be related to "orphanRemoval", because if I comment on its parent:

 @OneToMany(mappedBy = "parent" /*, orphanRemoval = true */) private List<Child> childs; 

It works!
He saves the child, then the parent.
But I really need the orphan to be removed through the cascade when I remove the child from its parent.

UPDATE 2
I created a JIRA problem:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-5364

UPDATE 3
Seems fixed :-)
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269

+7
java hibernate orphan one-to-many cascade
source share
2 answers

This was a problem in Hibernate, and now it is fixed:

http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269

+1
source share

You basically violate the restriction. The row in db that matches the parent does not exist, therefore there is no foreign key relationship that the child can use to refer to the parent. Add a saveOrUpdate call to the parent before doing this for the child.

(edit) I missed your cascade comment before reformatting. My recollection is that the cascade does not work upstream in this way; you still need to save the parent first.

0
source share

All Articles