以下是我的情况:我将包含双向父子关系的对象加载到我的数据库中。稍后,该对象将加载到我的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>
Child hibernate config:
<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在它被呈现给UI时成为List(特别是apache的LazyList)的特定实现。但是,当从DB中取出对象时,它不会以这种方式实现,因此我创建了一个从数据库中提取的常规List的LazyList副本,并调用setSpecimenTypes()将其替换为我新填充的LazyList。有谁知道我这样做的方法吗?
答案 0 :(得分:0)
您的映射看起来是正确的。你是如何除去孩子的?类似于getSpecimenTypes().remove(X)
的东西,或者你有一个特殊的方法(如果有的话,你可以发布它)吗?
此外,当您的父对象转移到UI层并返回时 - 是否在同一会话中完成?你确定没有人通过在中间的某个地方调用setSpecimenTypes()
来重置儿童收藏吗?
更新(基于澄清):
重置specimenTypes
肯定是个问题。 Hibernate如何知道你删除了一个特定的元素?删除是在Hibernate自己的PersistentList中跟踪的,当你加载父对象时它会包装你的列表。
LazyList(我假设你的意思是来自Commons Collections的那个)是一个装饰器,所以你可以在你的父对象中创建另一个getter方法,将你的specimenTypes
集合包装到LazyList中并返回它(缓存它)在成员变量中,在重复访问尝试期间提高效率。)
这里的底线是你永远不应该用你自己的版本覆盖Hibernate管理的集合。