我在Hibernate参考书的第21章中有一个基本的一对多关系父母/子女。 级联仅从子级到父级(持久级联仅是因为删除子级后我不希望删除父级)。 当我向父级添加一个子级并保存该子级时,我有一个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); }
但是在saveOrUpdate上,我有以下异常:
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)
我真的不明白,因为拯救孩子应该通过级联来拯救父母……有什么想法吗?
更新1 该问题似乎与“ orphanRemoval”有关,因为如果我在父级上对其进行评论:
@OneToMany(mappedBy = "parent" /*, orphanRemoval = true */) private List<Child> childs;
有用! 它保存了孩子,然后是父母。 但是,当我从父级中删除一个孩子时,我真的需要通过级联删除该孤儿。
更新3 似乎是固定的:-) http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269
这是Hibernate中的一个问题,现在已修复:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269