Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Realm copyToRealmOrUpdate creates duplicates of nested objects

Tags:

I have following classes:

public class Note extends RealmObject {

    @PrimaryKey
    private String id;

    private Template template;

    // other primitive fields, getters & setters
}

public class Template extends RealmObject {

    private String name;

    private String color;

    // other primitive fields, getters & setters
}

I get my data from backend via Retrofit & Gson, so I have ready-to-use java objects in response.

Let's imagine that backend returns me same three Notes each time I call it. When I get the list of Note objects, I do the following:

private void fetchNotesAndSave() {
    List<Notes> notes = getNotesViaRetrofit();        

    Realm realm = Realm.getInstance(mContext);
    realm.beginTransaction();
    realm.copyToRealmOrUpdate(notes);
    realm.commitTransaction();
    realm.close();
}

After that I call these lines to check count of stored objects:

int notesCount = mRealm.where(Note.class).findAll().size();
int templatesCount = mRealm.where(Template.class).findAll().size();

For the first time:

notesCount == 3;
templatesCount == 3;

That's right. But, if I call the server again, get same notes (same primaryKey ids), and call fetchNotesAndSave() again, I'll get these results:

notesCount == 3;
templatesCount == 6;

Each time I call copyToRealmOrUpdate(), nested objects, that are inside of objects with primaryKey are duplicated - not updated.

Is there any way to change this behaviour? Please let me know if you need more information. Thanks in advance!

like image 373
Oleksii Shliama Avatar asked May 15 '15 11:05

Oleksii Shliama


2 Answers

It is because your Template class doesn't have any primary key. In that case these objects are inserted again as there is no guarantee that the referenced template objects safely can be updated, even if they are part of another object that has a primary key.

If you add a @PrimaryKey to your template class it should work as you expect it to.

like image 158
Christian Melchior Avatar answered Sep 24 '22 01:09

Christian Melchior


If you can't provide a PK as suggested, you might want to use the following work around to avoid duplicates.

for (Note note: notes) {
    realm.where(Note.class)
    .equalTo("id", note.getId())
    .findFirst()
    .getTemplate()
    .deleteFromRealm();
}
realm.copyToRealmOrUpdate(notes);
like image 27
Nabil Hachicha Avatar answered Sep 22 '22 01:09

Nabil Hachicha