Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate : Best way to delete elements in a collection

Tags:

java

hibernate

A problem that I often face with Hibernate is having a list (call it listA) of objects that I want to persist against an entity (myEntity) but having to first compare them to the existing list on the entity and delete those that aren't in listA.

The simple way to do this is to clear the list on the Entity and just add all of listA to the entity, however I often have to perform some validation on the elements before they are deleted - eg. to check whether this user is allowed to delete them.

My current approach feels awkward:

//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);
    }
}

Any room for improvement?

Thanks.

like image 556
Damo Avatar asked Apr 16 '09 14:04

Damo


2 Answers

I know this question is quite old, but I ran in the same problem and I think the answers given were not enough. So, you could achieve at the exact result you want just adding the property "orphanRemoval=true" to you mapping annotation. Orphan removal works this way (as described in the page 136 of the book "Beginning Java EE 6 Platform with GlassFish 3":

"[...] the code will automatically remove the Address entity when the customer is removed, or when the relationship is broken (by setting to null the address attribute or by removing the child entity from the collection in a one-to-many case)".

That is, if you remove an item from a collection mapped with orphan removal and then merge the entity, this item will be also removed.

like image 97
Saul Berardo Avatar answered Nov 20 '22 00:11

Saul Berardo


Try using:

myEntity.getObjectAList().removeAll(listA);

this will only keep the objects which aren't already in listA.

Also, if you need to do something like this manually in the future, use an iterator:

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

Then it.next() will give you the next item in the array, and it.remove() will remove the last value of next() for you, without giving an exception if you keep looping.

If you need to also have the ability to add a new value while looping, consider using listIterator() instead.

like image 20
Zack Marrapese Avatar answered Nov 20 '22 00:11

Zack Marrapese