I have a basic one to many relation parent / child like in the chapter 21 of Hibernate references book.
The cascade is only from child to parent (persist cascade only because I don't want to delete the parent if I delete a child).
When I add a child to the parent and I save the child, 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 the 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 the Child should save the Parent via the cascade... Any ideas ?
UPDATE 1
The problem seems to be related to "orphanRemoval" because if I comment it on the parent:
@OneToMany(mappedBy = "parent" /*, orphanRemoval = true */)
private List<Child> childs;
It works!
It save the child, then the parent.
But I really need the orphan to be deleted via the cascade when I remove a child from its parent. 
UPDATE 2
I've created a JIRA issue:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-5364
UPDATE 3
It seems to be fixed :-)
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269
It was an issue in Hibernate and it is now fixed:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With