Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parent Child delete not working with ConcurrentModificationException - tried diff ways #899

Closed
vvictor10 opened this issue Feb 24, 2015 · 13 comments

Comments

@vvictor10
Copy link

Simple relationship - Car has 1 or more tires. Using version 0.79.1. Due to the absence of cascade delete support, I am trying to delete the children before deleting the parent object(as part of the result collection).

In all cases, I get the same exception. Can you guys tell me how I am supposed to handle this? Cascade delete would be perfect, I just would love to save RealmResult.clear(). Without that, how do I delete the parent and the children. Thanks in advance.

java.util.ConcurrentModificationException: No outside changes to a Realm is allowed while iterating a RealmResults. Use iterators methods instead.
        at io.realm.RealmResults.assertRealmIsStable(RealmResults.java:507)
        at io.realm.RealmResults.access$200(RealmResults.java:55)
        at io.realm.RealmResults$RealmResultsIterator.hasNext(RealmResults.java:524)

Option 1:

    realm.beginTransaction();
    RealmResults<RealmCar> cars = realm.where(RealmCar.class).findAll();
    // Cascade delete is not available as of version 0.79.1.
    for(RealmCar car : cars){
        car.getTires().clear();
    }
    int result = cars.size();
    cars.clear();
    realm.commitTransaction();

Option 2:

    realm.beginTransaction();
    RealmResults<RealmCar> cars = realm.where(RealmCar.class).findAll();
    // Cascade delete is not available as of version 0.79.1.
    for(RealmCar car : cars){
        Iterator<RealmTire> tireIterator = car.getTires().iterator();
        while(tireIterator.hasNext()){
            tireIterator.next().removeFromRealm();
        }
    }
    int result = cars.size();
    cars.clear();
    realm.commitTransaction();

Option 3:

    realm.beginTransaction();
    RealmResults<RealmCar> cars = realm.where(RealmCar.class).findAll();
    // Cascade delete is not available as of version 0.79.1.
    Iterator<RealmCar> carIterator = cars.iterator();
    while(carIterator.hasNext()){
        Iterator<RealmTire> tireIterator = carIterator.next().getTires().iterator();
        while(tireIterator.hasNext()){
            tireIterator.next().removeFromRealm();
        }
    }
    int result = cars.size();
    cars.clear();
    realm.commitTransaction();
    realm.close();
@emanuelez
Copy link
Contributor

Hello,
that is an area of the API we need to improve and we are working on it.
While we fix this you could try something like this:

for (int i = cars.size() - 1; i >= 0; i--) {
   Car car = cars.get(i);
   List<Tire> tires = car.getTires();
   for (int j = tires.size() - 1; j >= 0; j--) {
      tires.get(j).removeFromRealm();
   }
}

@vvictor10
Copy link
Author

First of all, thanks a lot for the almost immediate response.
That worked. Any idea when we can get the cascade delete feature?

@emanuelez
Copy link
Contributor

That's a controversial issue since there is no right way to handle cascading deletes.
For some use cases you want it to be aggressive while in others you want it to be conservative, so it's a hard balance.

For example, imagine you have a Developer class and an Issue class. A developer can be assigned to several issues.
If that developer leaves the company you only want to delete him and not the issues he's assigned to.

So we need to be able to support all use cases and the current state, while vastly sub-optimal, is at least flexible enough to handle all the use-cases we came across so far.

@vvictor10
Copy link
Author

@emanuelez Agreed. No doubt, but it should be configurable through an annotation at least? I am thinking that there would be more parent/child relationship where the Child makes no sense without a parent than the other way(for e.g. like the one you are mentioning). In all those cases, it would be super useful to just blow the whole thing away in one method call.

@mmvicsonvictor
Copy link

The suggested alternative is a pretty slow operation as you can tell. I have a car which has 4 tires. To delete 10000 cars(4 tires each) takes about 13 seconds, which is unacceptable even on a background operation. I can see several applications performing background syncs where wiping data and recreating them is pretty common.

Before you guys address the cascade issue, can we have an interim solution to delete all the children in one shot? Something like a removeAllFromRealm() on a list.

This is my current code, is there a better way to do it?

    Realm realm = realmInstanceFactory.getInstance();
    realm.beginTransaction();
    RealmResults<RealmCar> cars = realm.where(RealmCar.class).findAll();
    int result = cars.size();

    if(result != 0){
        for (int i = cars.size() - 1; i >= 0; i--) {
            RealmCar car = cars.get(i);
            List<RealmTire> tires = car.getTires();
            for (int j = tires.size() - 1; j >= 0; j--) {
                tires.get(j).removeFromRealm();
            }
        }
        cars.clear();
    }
    realm.commitTransaction();
    realm.close();

@cmelchior cmelchior added the P1 label Apr 15, 2015
@mmvicsonvictor
Copy link

@cmelchior Has there been any movement on this issue? Thanks.

@osayilgan
Copy link

@emanuelez is there any progress on this issue ? It's a sort of critical issue for my case.

@lukcz
Copy link

lukcz commented Jun 18, 2015

@emanuelez any timeframe for this? As @osayilgan already said this is kind of critical functionality (also for me)

@mustafa01ali
Copy link

Bump. Any update on this?

@emanuelez
Copy link
Contributor

Yes, we now have the functionality we needed from the core so we can now implement it in the binding

@aercanozcan
Copy link

do we have it now?

@emanuelez
Copy link
Contributor

This issue can be splitted in two major parts:

  • Cascading deletes: this is being worked on by the core tram
  • Being able to delete items while iterating: this high in the to-do list of the java team

@cmelchior
Copy link
Contributor

As @emanuelez says, this issue is already covered by #1104 and #640. So i'll close this as an duplicate.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants