我经常面对Hibernate的一个问题是有一个列表(称之为listA)我希望对实体(myEntity)持久化的对象,但必须首先将它们与实体上的现有列表进行比较并删除那些不在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);
}
}
还有改进空间吗?
感谢。
答案 0 :(得分:18)
我知道这个问题已经很老了,但我遇到了同样的问题,我认为给出的答案还不够。因此,您可以在确切的结果中实现,只需将属性"orphanRemoval=true"
添加到映射注释即可。孤立删除以这种方式工作(如“使用GlassFish 3开始Java EE 6平台”一书的第136页所述:
“[...]代码将在删除客户时或关系中断时自动删除地址实体(通过将地址属性设置为null或通过从集合中删除子实体< / strong>在一对多的情况下)“。
也就是说,如果从使用孤立删除映射的集合中删除某个项目然后合并该实体,则该项目也将被删除。
答案 1 :(得分:11)
尝试使用:
myEntity.getObjectAList().removeAll(listA);
这只会保留未在listA中的对象。
此外,如果您将来需要手动执行此类操作,请使用迭代器:
Iterator<?> it = myEntitiy.getObjectAList().iterator();
while (it.hasNext())
{
...
}
然后it.next()将为你提供数组中的下一个项目,it.remove()将为你删除next()的最后一个值,如果你继续循环则不会给出异常。
如果您还需要在循环时添加新值,请考虑使用listIterator()代替。