Closed laindow closed 8 years ago
Hi @laindow Thank you for your suggestion. Instead of using reflection it might be easier to make a special method in your model classes that does this instead:
public class Foo extends RealmObject {
public RealmList<Foo> list;
public String name;
public void cascadeDelete() {
list.deleteAllFromRealm(); // The cascade part
deleteFromRealm(); // delete this object
}
}
Your approach is more generic though, which also has a lot of merrit. This is already being tracked in #1104 though, so i'll close this as a duplicate.
Hi guys,
This is a general solution. You don't need to implement delete function for each model. It can delete your whole objects structure even if it complicated. If you add a property to the model you don't need to rewrite delete function. Sadly payment for that is performance. Reflection always more slow if compare with direct call but if you don't have huge amount of records and your models structure complicated it would be better solution.
Best regards, Konstantin.
@cmelchior Your suggested solution won't work correctly if Foo contains any Realm Models. They'll be orphaned when their parent Foo is deleted right?
Yes, that is correct. You will need to manually delete all references in the cascadeDelete
method.
public class Foo extends RealmObject {
public RealmList<Foo> list;
public Bar bar;
public String name;
public void cascadeDelete() {
list.deleteAllFromRealm(); // The cascade part
if (bar != null) {
bar.deleteFromRealm();
}
deleteFromRealm(); // delete this object
}
}
What about when updating an existing nested realmObject with copyToRealmOrUpdate()
?
@fryossi if I know correctly, copyToRealmOrUpdate()
goes through all objects in the hierarchy - although technically if you modify a managed RealmObject, then you don't have to call copyToRealmOrUpdate()
on it to update its fields.
@fryossi If you call copyToRealmOrUpdate() on an existing root object, it will overwrite the child objects with their new data. Note: You'll have orphaned children if the updated root object no longer refers to them. For example Person "Bob" refers to two Dogs, "Fox" and "Rex". But then "Fox" dies and when you call copyToRealmOrUpdate() with a new version of "Bob" you'll still have "Fox" dangling in Realm but "Bob" no longer refers to it.
You'll have orphaned children if the updated root object no longer refers to them
@Zhuinden and @snowpong - I know, that's the problem! There's a workaround for deletion but how to avoid it on updating with copyToRealmOrUpdate()
?
if you modify a managed RealmObject, then you don't have to call copyToRealmOrUpdate() on it to update its fields
@fryossi assuming you have a new "Bob" gotten from a REST server for example, to update it do this in a Transaction:
realm.where(Person.class).equalTo("id", newBob.getId()).findFirst()
oldBob.getDogs().deleteAllFromRealm()
realm.copyToRealmOrUpdate(newBob)
Note: This assumes the dogs can only have one owner.
So you are saying there's no option but delete its children.
@fryossi A more elegant solution is to remove only the children that are no longer referred to in the updated parent. You could possibly do something like:
oldBob.getDogs().where().not().in("id", arrayOfDogIdsFromNewBob).deleteFromRealm()
before calling copyToRealmOrUpdate(newBob)
Thanks.
In a situation when many People can refer the same Dogs in their lists, removing lost Dogs may act like GC and can be quite time-consuming š š
i don't get what is the deal here. While you can add object and its sub objects without problem, why can't you delete them? You have the index of sub objects ?!
I think Realm-Core does have support for cascading now.
The question here of course is that if you delete the parent object with RealmResults.deleteAllFromRealm()
, then its connected objects should also be automatically deleted by Realm.
That'll happen eventually.
Maybe you are right, have not tried on latest version, didn't work on 3.2.0 (a bit old)
No it is not supported by the Java binding yet, still manual
Since after so many years there is still no native approach for cascading deletes, could the Realm Java team at least please provide a temporary generic solution based on the latest version of Realm? Something like what @laindow provides in this issue's description, but updated for the latest version of the library in both Java and Kotlin?
The Realm Swift community (not the actual development team) has come up with some pretty decent solutions over the years.
Some of our projects have tens of very large model types that get updated frequently. Do we have to force our team to update both the migration code AND the cascade deletion code? It's a very error-prone procedure.
I think this problem should not be ignored any more. Most Android and iOS projects I've seen based on Realm just don't implement cascade deletes at all! Both the API and Realm's "simple to use" promotion is deceiving many developers into thinking that the current model delete methods actually clean up everything!
I personally believe that cascade deletes should have been available ages ago, but I understand that resources are limited. However, a temporary "official" generic approach should be prominently available in the documentation until the native solution becomes available... I can't believe that your best suggestion is to have us implement this manually for each one of our model types.
Both the API and Realm's "simple to use" promotion is deceiving many developers into thinking that the current model delete methods actually clean up everything!
Did they ever really say that? You delete an object, nobody auto-clears the linked objects. Imagine this, if the owner of a dog is deleted, the dog lives on.
The best way to avoid hard-to-manage cascade deletion is to use as low number of links as possible. For example, forward-facing uni-directional links can be merged into the same object, inheriting the fields from the supposed linked class.
I am still not a member of Realm, but my links have never been so hard to manage. Worst thing that happened was 3 long but that was unavoidable as they were all lists from one to another.
I would think lately, using @LinkingObjects
can verify that there are no linked objects pointing to you, so you can safely remove your object.
I also think that Realm-Core has supported this since 1.5 years ago, but I think Realm Sync got in the way of eventually ever adding the concept of @StrongRelation
. A shame that Sync held back the development of the Database.
Both the API and Realm's "simple to use" promotion is deceiving many developers into thinking that the current model delete methods actually clean up everything!
Did they ever really say that? You delete an object, nobody auto-clears the linked objects. Imagine this, if the owner of a dog is deleted, the dog lives on.
No, the Realm team didn't explicitly state that cascading deletes are handled automatically. However the easiness of creating relationships and the fact that the documentation has a whole section on them, lures most developers into thinking that everything (including cascading deletion) is handled automatically under the hood.
I've been using Realm since 2015 on some relatively demanding applications and I remember how difficult it had been to implement manual cascading deletion for a set of models with complex relations back then. In fact, I would say that the lack of this feature and the Realm threading approach have been the two biggest problems myself and most of the devs I've talked to had to handle.
Yesterday I was asked to evaluate the code of an application that uses Realm and noticed that it does not handle cascading deletion either! It's maybe the 10th time I'm seeing this on an app! The devs just did not realise that when you delete the "owner", their "dogs" stay behind. The story is always the same: Let's download some inter-related data from a REST API and save them to easy-to-use Realm. It's so easy to save them, that deleting them must be easy too.
I believe that until cascading deletes are implemented, the documentation should at least explicitly mention that they are not supported and point to an "official" temporary generic solution. It should also warn users that this temporary approach might hurt performance and offer examples of how to implement cascading deletes manually for each model type.
IMHO the current state of the documentation is severely lacking in that respect, plus I think that the best "generic" solution one can find online is the one at the beginning of this post. Java-only and implemented with Realm 0.89.
While I understand the sentiment, I can't blame Realm for people misunderstanding how object deletion works.
And the "threading approach" is only a problem because devs often create this infinite nesting of thread jumps and Realm is totally legit saying "hey, we don't trust what you're trying to do here". In a way, Realm encourages code to be better, and for the developer to at least remotely care about what on earth they're doing.
Saying Realm's threading is hard is akin to saying "the way to fix NetworkOnMainThreadException is overriding Strict Mode to allow main thread network requests". No.
If people had a better understanding of concurrency, and wouldn't want to throw their code to execute on seemingly random threads, then they wouldn't find Realm's threading model difficult.
I am still not a member of Realm, and that's just my personal opinion.
However, I do admit that the addition of @StrongRelationship
would have greatly improved the Realm Database, and it's regretful that it got stuck in limbo in 2018 and then never happened.
I would like to thank you for replying in the first place and I agree with you that none of the issues I am raising is strictly a problem of the technology.
I am not blaming Realm for anything either. In fact I have been a very strong supporter for it since its early days. I have also made some serious architectural decisions involving Realm in multiple projects, because I do believe the technology is good and the people behind it are capable.
I just think that since this functionality is something that many developers need (and it seems some don't even know they do) and since it hasn't been implemented in a long time, an official temporary cascading delete solution and an update of the related documentation will greatly benefit both the project itself and the community.
Hello guys
Goal
It would be great to have "cascade delete" operation.
Expected Results
When I call Realm.removeFromRealm() function I wanna delete current Realm object and all child Realm objects.
Actual Results
At this stage if I delete Realm object all child objects stay in DB.
Code Sample
I am already made some code and happy to share it with you to make your great framework even better. May be it will be useful for someone.
Interface to make "cascade delete" optional
Generic "cascade delete" function
Model example
"How to use?"
Version of Realm and tooling
Realm version(s): 0.89
Android Studio version: 2.1
Which Android version and device: Any