web-dev-qa-db-ja.com

AndroidレルムcopyToRealmOrUpdateは、ネストされたオブジェクトの複製を作成します

私は次のクラスを持っています:

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
}

Retrofit&Gsonを介してバックエンドからデータを取得するので、すぐに使用できるJavaオブジェクトが応答します。

バックエンドが呼び出すたびに同じ3つのノートを返すと想像してみましょう。 Noteオブジェクトのリストを取得したら、次のようにします。

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

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

その後、これらの行を呼び出して、保存されているオブジェクトの数を確認します。

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

初めて:

notesCount == 3;
templatesCount == 3;

そのとおり。ただし、サーバーを再度呼び出し、同じメモ(同じprimaryKey id)を取得し、fetchNotesAndSave()を再度呼び出すと、次の結果が得られます。

notesCount == 3;
templatesCount == 6;

CopyToRealmOrUpdate()を呼び出すたびに、primaryKeyを持つオブジェクトの内部にあるネストされたオブジェクトが複製され、更新されません。

この動作を変更する方法はありますか?さらに詳しい情報が必要な場合はお知らせください。前もって感謝します!

18
Oleksii Shliama

これは、テンプレートクラスに主キーがないためです。その場合、これらのオブジェクトは、参照されたテンプレートオブジェクトが主キーを持つ別のオブジェクトの一部であっても、安全に更新できる保証がないため、再度挿入されます。

テンプレートクラスに@PrimaryKeyを追加すると、期待どおりに機能するはずです。

21

提案されているようにPKを提供できない場合は、重複を避けるために次の回避策を使用することをお勧めします。

for (Note note: notes) {
    realm.where(Note.class)
    .equalTo("id", note.getId())
    .findFirst()
    .getTemplate()
    .deleteFromRealm();
}
realm.copyToRealmOrUpdate(notes);
3
Nabil Hachicha