J'ai un parent-enfant de base à plusieurs comme dans le chapitre 21 du livre de références d'Hibernate.
La cascade est uniquement d'enfant à parent (persistez en cascade uniquement parce que je ne veux pas supprimer le parent si je supprime un enfant).
Quand j'ajouter un enfant au parent et je sauve l'enfant, j'ai TransientObjectException ...Hibernate - Relation un-à-plusieurs et cascade OrphanRemoval
@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);
}
Mais le saveOrUpdate, je cette 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)
Je vraiment don ne comprends pas car sauver l'Enfant devrait sauver le Parent via la cascade ... Des idées?
MISE À JOUR 1
Le problème semble être lié à "orphanRemoval" parce que si je commente sur le parent:
@OneToMany(mappedBy = "parent" /*, orphanRemoval = true */)
private List<Child> childs;
ça marche!
Il sauve l'enfant, puis le parent.
Mais j'ai vraiment besoin que l'orphelin soit supprimé via la cascade lorsque je retire un enfant de son parent.
MISE À JOUR 2
J'ai créé un problème JIRA:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-5364
MISE À JOUR 3
Il semble être fixé :-)
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269
Bienvenue sur Stack Overflow! Utilisez le bouton avec des zéros et ceux pour formater correctement votre code dans le futur (je l'ai formaté pour vous). –
Merci ... nous l'avons fait en même temps ;-) –
Que se passe-t-il si vous enregistrez le parent avant d'enregistrer l'enfant? – Kendrick