Hibernate无法从数据库中删除子项

Hibernate无法从数据库中删除子项,hibernate,Hibernate,我的情况如下:我将包含双向父子关系的对象加载到数据库中。稍后,该对象将加载到我的UI中,可以在其中进行更改,包括从子集中删除任意数量的子对象。然后使用saveOrUpdate方法加载我的对象的这个修改副本。但是,保存此修改副本后,所有已删除的子项都会保留在数据库中,添加到集合中的新子项可以正常工作。在整个过程中没有抛出错误,但我需要从数据库中实际删除这些已删除的子项。我已经在下面粘贴了hibernate和java代码的相关部分 父休眠配置: <bag name="specimenTypes

我的情况如下:我将包含双向父子关系的对象加载到数据库中。稍后,该对象将加载到我的UI中,可以在其中进行更改,包括从子集中删除任意数量的子对象。然后使用saveOrUpdate方法加载我的对象的这个修改副本。但是,保存此修改副本后,所有已删除的子项都会保留在数据库中,添加到集合中的新子项可以正常工作。在整个过程中没有抛出错误,但我需要从数据库中实际删除这些已删除的子项。我已经在下面粘贴了hibernate和java代码的相关部分

父休眠配置:

<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" />
编辑:


显然,我的问题是因为在从数据库检索父对象之后,在保存更新的对象之前,显式调用setSpecimenTypes。我这样做的原因是,由于一些动态列表绑定,我需要列表在呈现给UI时是特定于列表的实现,特别是apache的LazyList。但是,当对象从DB中提取时,它不是以这种方式实现的,因此我创建了从数据库中提取的常规列表的LazyList副本,并调用setSpecimenTypes将其替换为新填充的LazyList。有人知道我该怎么做吗?

您的映射看起来是正确的。你怎么把孩子们搬走?类似于getSpecimenTypes.removeX的东西,或者你有专门的方法吗?如果有,你能发布它吗

另外,当父对象被传输到UI层并返回时,是否在同一会话中完成?您确信没有人通过调用StEngestEnter类型在中间重新设置子集合吗?

根据澄清更新:

重置specimenTypes肯定是个问题。Hibernate如何知道您已经删除了一个特定的元素?在Hibernate自己的PersistentList中跟踪删除,当加载父对象时,它会包装您的列表

LazyList我假设您的意思是Commons集合中的那个是一个装饰器,因此您可以在父对象中创建另一个getter方法,该方法将specimenTypes集合包装到LazyList中,并将其缓存在成员变量中,以提高重复访问尝试期间的效率


这里的底线是,您永远不应该用自己的版本覆盖由Hibernate管理的集合。

我在更新对象之前调用setSpecimenTypes,原因我在我的文章的更新中概述过,但我不明白为什么这很重要。是否应该更新子列表以反映当前子集包含的内容,从而删除任何旧的子数据库条目?谢谢帮助。但我仍然有一个问题。当我更改getter以返回修饰列表时,当父类从DB中提取时,我得到以下错误:拥有实体实例不再引用cascade=all delete orphan的集合。我确信setSpecimenTypes从未被调用,我甚至将其私有化。您在上面提到我应该创建另一个getter,而不是像我那样替换当前的getter。我的方法不正确有什么原因吗?从现有getter返回修饰列表的问题是它不再是Hibernate的PersistentList。Hibernate不知道您已经包装了它,也不知道如何打开它——它只是看到原来的PersistentList现在不见了——因此出现了异常。您确实需要另一个getter,但是如果您的代码依赖于getSpecimentTypes,您可以创建一个私有getSpecimentTypesDB并在Hibernate中映射它。我个人更喜欢装饰UI bean,而不是业务对象,但这两种方法都有自己的位置。
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;
}