2015-05-15 2 views
12

Я следующие классы:Android Realm 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 в ответ.

Давайте представим, что бэкэнд возвращает мне то же три Notes каждый раз, когда я его вызываю. Когда я получаю список Примечание объектов, я делаю следующее:

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 идентификаторы), и вызвать fetchNotesAndSave() еще раз, я получаю эти результаты:

notesCount == 3; 
templatesCount == 6; 

Каждый раз, когда я называю copyToRealmOrUpdate(), вложенные объекты, которые находятся внутри объектов с primaryKey, дублируются - не обновляются.

Есть ли способ изменить это поведение? Пожалуйста, дайте мне знать, если вам нужна дополнительная информация. Заранее спасибо!

ответ

13

Это потому, что ваш класс шаблонов не имеет первичного ключа. В этом случае эти объекты снова вставляются, поскольку нет гарантии, что ссылочные объекты шаблонов могут быть обновлены, даже если они являются частью другого объекта с первичным ключом.

Если вы добавите @PrimaryKey в свой шаблонный класс, он должен работать так, как вы ожидаете.

+1

Я понимаю это, но в моем случае существует много вложенных классов, и я не могу создать '@ PrimaryKey' для каждого из них. И, например, я использую этот трюк для обработки списка строк https://github.com/realm/realm-java/issues/575, поэтому я должен генерировать '@ PrimaryKey' для каждого из' RealmString'. Это будет настоящий ад ... –

+2

Есть ли какое-либо обходное решение, чтобы поддерживать вложенные отношения друг с другом в один класс с суперклассом без '@ PrimaryKey', поэтому они обновлены правильно? –

+0

В настоящее время нет. Вам придется выполнять эту очистку вручную. –

2

Если вы не можете предоставить PK, как было предложено, вы можете использовать следующую работу, чтобы избежать дублирования.

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

Это обсуждалось здесь https://github.com/realm/realm-java/issues/2918#issuecomment-222950343 – EpicPandaForce

Смежные вопросы