这是我的情况:我将一个包含双向父亲子关系的对象加载到我的数据库中。稍后,该对象会加载到可以进行更改的UI中,其中包括从子集中删除任意数量的子项。然后使用saveOrUpdate方法加载此对象的修改副本。但是,保存此修改后的副本时,任何已删除的子项都保留在数据库中(新添加的子元素可以正常工作)。在整个过程中不会出现任何错误,但我需要将这些删除的子项实际从数据库中删除。我在下面粘贴了我的hibernate和java代码的相关部分。Hibernate无法从数据库中删除子项
父冬眠配置:
<bag name="specimenTypes" table="masterPkSpecimenType" cascade="all-delete-orphan" inverse="true">
<key column="runid"/>
<one-to-many class="SpecimenType"/>
</bag>
儿童冬眠配置:
<many-to-one name="reportCriteriaBean" class="ReportCriteriaBean" column="runid" not-null="true" />
父对象代码:
public List<SpecimenType> getSpecimenTypes() {
return specimenTypes;
}
public void setSpecimenTypes(List<SpecimenType> specimenTypes) {
this.specimenTypes = specimenTypes;
if(this.specimenTypes != null){
for(SpecimenType specType : this.specimenTypes){
specType.setReportCriteriaBean(this);
}
}
}
子对象代码:
public ReportCriteriaBean getReportCriteriaBean() {
return reportCriteriaBean;
}
public void setReportCriteriaBean(ReportCriteriaBean reportCriteriaBean) {
this.reportCriteriaBean = reportCriteriaBean;
}
编辑:
显然,我的问题是由于显式调用setSpecimenTypes()后,我从数据库中检索父对象,在此之前我保存更新的对象回来。我这样做的原因是,由于一些动态的List绑定,我需要List作为List的具体实现(特别是apache的LazyList),当它呈现给UI时。但是,当对象从数据库中拉出时,它不会以这种方式实现,所以我创建了从数据库中拉出的常规列表的LazyList副本,并调用setSpecimenTypes()将其替换为新填充的LazyList。有没有人知道我的方式做到这一点?
我在更新对象之前调用setSpecimenTypes()(因为我在文章的更新中列出的原因),我不明白为什么这很重要。不应该更新子列表以反映当前的子集所包含的任何内容,从而删除任何旧的子数据库条目? – TimmyJ 2009-08-06 20:48:10
感谢您的帮助。我仍然有一个问题,但。当我将getter更改为返回装饰的列表时,当父类从DB中拉出时,出现以下错误: 具有cascade =“all-delete-orphan”的集合不再由拥有的实体实例引用。 我相信,setSpecimenTypes永远不会被调用(我甚至把它设为私有)。你在上面提到我应该创建*另一个* getter,而不是像我那样替换当前的那个。我的方式会不正确吗? – TimmyJ 2009-08-07 16:42:18
从现有getter返回修饰列表的问题是它不再是Hibernate的PersistentList。 Hibernate不知道你已经封装了它(或者如何解开它) - 它只是看到那里的PersistentList现在已经消失 - 因此是例外。你确实需要另一个getter,但是如果你的代码依赖于getSpecimenTypes(),你可以创建一个私有的'getSpecimentTypesDB()'并映射到Hibernate中。我个人比较喜欢装饰UI bean而不是业务对象,但是任何一种方法都有它的位置。 – ChssPly76 2009-08-07 17:01:28