休眠:删除集合中元素的最佳方式

2022-09-02 09:39:41

我经常在Hibernate上遇到的一个问题是,有一个列表(称为listA)的对象,我想对实体(我的实体)持久化,但必须首先将它们与实体上的现有列表进行比较,并删除那些不在listA中的对象。

执行此操作的简单方法是清除实体上的列表,然后将所有listA添加到实体中,但是我经常必须在删除元素之前对元素执行一些验证 - 例如。以检查是否允许此用户删除它们。

我现在的方法感觉很尴尬:

//Delete the elements that have been removed
//Use toArray to avoid ConcurrentModificationException
for(ObjectA a : myEntity.getObjectAList().toArray(new ObjectA[myEntity.getObjectAList().size()])) {
    if(!listA.contains(a)) {

        //Check if this element can be deleted
        if(canDelete(a)) {
            entityManager.remove(a);
            myEntity.getObjectAList().remove(a);
        }
    }
}

//Add the elements that don't already exist
for(ObjectA a : listA) {
    if(!myEntity.getObjectAList().contains(a)) {
        myEntity.getObjectAList().add(a);
    }
}

还有改进的余地吗?

谢谢。


答案 1

我知道这个问题已经很老了,但我遇到了同样的问题,我认为给出的答案还不够。因此,您可以达到您想要的确切结果,只需将属性添加到映射注释中即可。孤儿删除以这种方式工作(如“用 GlassFish 3 开始 Java EE 6 平台”一书的第 136 页所述):"orphanRemoval=true"

"[...]当客户被删除时,或者当关系中断时(通过设置为 null 地址属性或在一对多情况下从集合中删除子实体),代码将自动删除地址实体”。

也就是说,如果从使用孤立项删除映射的集合中删除项,然后合并实体,则此项也将被删除。


答案 2

尝试使用:

myEntity.getObjectAList().removeAll(listA);

这将仅保留尚未在 listA 中的对象。

另外,如果将来需要手动执行此类操作,请使用迭代器:

Iterator<?> it = myEntitiy.getObjectAList().iterator();
while (it.hasNext())
{
    ...
}

然后 it.next() 会给你数组中的下一项,it.remove() 会为你删除 next() 的最后一个值,如果你继续循环,不会给出一个例外。

如果您还需要能够在循环时添加新值,请考虑改用 listIterator()。


推荐