Android,Realm:After add annotation@PrimaryKey get错误:以下更改无法在仅添加模式下进行:

Android,Realm:After add annotation@PrimaryKey get错误:以下更改无法在仅添加模式下进行:,android,realm,Android,Realm,领域3.5.0。 我从外部系统获取json。我需要将这个json保存到Realm 此处: { "id": 1, "address": "Address 1", "contactsIds": [10, 20, 30, 40], "name": "Person 1" } 在我的Android应用程序中: 因此,我为Person创建了POJO: public class Person extends RealmObject { @PrimaryKey

领域3.5.0。 我从外部系统获取json。我需要将这个json保存到Realm

此处:

{
    "id": 1,
    "address": "Address 1",
    "contactsIds": [10, 20, 30, 40],
    "name": "Person 1"
}
在我的Android应用程序中:

因此,我为Person创建了POJO:

public class Person extends RealmObject {
    @PrimaryKey
    private int id;
    @Required
    private String name;
    private String address;
    private RealmList<RealmInt> contactsIds = new RealmList<>();
}
我的RealmInt自定义json反序列化程序(由GSON提供):

调用方法“fromJsonToRealm”的结果是:

  • 在表“Person”中创建了一条记录
  • 在表“RealmInt”中创建了4条记录(10、20、30、40)

表“Person”和“RealmInt”必须与许多Android设备共享。因此,我使用了同步配置。 下面是一段:

    private void setRealmDefaultConfiguration(SyncUser syncUser) { 
         SyncConfiguration config = new SyncConfiguration.Builder(syncUser, REALM_URL).build();
        Realm.setDefaultConfiguration(config); 
    } 
所以现在我想更新这个人。 我得到了新的json(对于相同的),其中包含更新的数据:

{
    "id": 1,
    "address": "Address new",
    "contactsIds": [10, 20],
    "name": "Person new"
}
我再次启动方法“fromJsonToRealm”,结果它成功地更新了表“Person”中的一条记录,但在表“RealmInt”中添加了新的2条记录。 结果在表“RealmInt”中,我有6条记录

但我想在更新同一对象“Person”时更新(而不是插入)表“RealmInt”中的记录

因此,我将注释@PrimaryKey添加到对象“RealmInt中的字段“value”

但当我从JSONTORealm重新启动方法“”时,我得到错误:

E/REALM_JNI( 9018): jni: ThrowingException 8, The following changes cannot be made in additive-only schema mode:
E/REALM_JNI( 9018): - Primary Key for class 'RealmInt' has been added., .
E/REALM_JNI( 9018): Exception has been thrown: The following changes cannot be made in additive-only schema mode:
E/REALM_JNI( 9018): - Primary Key for class 'RealmInt' has been added.

所以问题是:当获取同一对象的更新json时,如何更新表“Person”中的exist记录?

添加/删除
@PrimaryKey
被视为“破坏性”模式操作,因此在同步模式下不允许

使用当前的模式设置,在复制新用户之前,应该从域中删除现有的
RealmInt
s

public void fromJsonToRealm(final String someJson) {
    try(Realm realm = Realm.getDefaultInstance()) {
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
               Person person = JsonUtil.gson.fromJson(someJson, Person.class);
               long personId = person.getId();
               Person managedPerson = realm.where(Person.class).equalTo("id", personId).findFirst();
               if(managedPerson != null) {
                   managedPerson.getContactIds().deleteAllFromRealm();
               }
               realm.copyToRealmOrUpdate(person);
            }
        });
    }
另一个选择是实现一些更智能的合并逻辑

public void fromJsonToRealm(final String someJson) {
    try(Realm realm = Realm.getDefaultInstance()) {
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
               Person person = JsonUtil.gson.fromJson(someJson, Person.class);
               long personId = person.getId();
               Person managedPerson = realm.where(Person.class).equalTo("id", personId).findFirst();
               if(managedPerson != null) {
                   boolean wasFound = false;
                   for(RealmInt existingInt : managedPerson.getContactIds()) {
                       for(RealmInt newInt : person.getContactIds()) {
                           if(existingInt.getValue() == newInt.getValue()) {
                               wasFound = true;
                               break;
                           }
                       }
                       if(!wasFound) {
                           existingInt.deleteFromRealm();
                       }
                   }
                   Iterator<RealmInt> newIntIterator = person.getContactIds().iterator();
                   while(newIntIterator.hasNext()) {
                       RealmInt newInt = newIntIterator.next();
                       boolean wasFound = false;
                       for(RealmInt existingInt : managedPerson.getContactIds()) {
                           if(existingInt.getValue() == newInt.getValue()) {
                               wasFound = true;
                               break;
                           }
                       }
                       if(!wasFound) {
                           newIntIterator.remove();
                       }
                   }
               }
               realm.copyToRealmOrUpdate(person);
            }
        });
    }
public void fromJsonToRealm(最终字符串someJson){
try(Realm-Realm=Realm.getDefaultInstance()){
realm.executeTransactionAsync(新realm.Transaction(){
@凌驾
公共void执行(领域){
Person-Person=JsonUtil.gson.fromJson(someJson,Person.class);
long personId=person.getId();
Person-managedPerson=realm.where(Person.class).equalTo(“id”,personId).findFirst();
if(managedPerson!=null){
布尔值wasFound=false;
对于(RealmInt existingInt:managedPerson.getContactIds()){
for(RealmInt newInt:person.getContactIds()){
如果(existingInt.getValue()==newInt.getValue()){
wasFound=true;
打破
}
}
如果(!wasFound){
existingInt.deleteFromRealm();
}
}
迭代器newIntIterator=person.getContactIds().Iterator();
while(newIntIterator.hasNext()){
RealmInt newInt=newIntIterator.next();
布尔值wasFound=false;
对于(RealmInt existingInt:managedPerson.getContactIds()){
如果(existingInt.getValue()==newInt.getValue()){
wasFound=true;
打破
}
}
如果(!wasFound){
newIntIterator.remove();
}
}
}
realm.copyToRealmOrUpdate(个人);
}
});
}

另外,我不使用
RealmList
S,我更喜欢将它们保存为逗号分隔的字符串。不过,Realm Core 3.0.0将使此用例更容易使用。

仅添加模式模式
您正在使用SyncConfiguration,对吗?是的。这里的代码:
私有void setRealmDefaultConfiguration(SyncUser SyncUser){SyncConfiguration config=new SyncConfiguration.Builder(syncUser,REALM_URL).build();REALM.setDefaultConfiguration(config);}
。表“Person”和“RealmInt”必须与许多其他android设备共享。所以您认为使用Field personsIds作为字符串是更好的方法吗?Smt如下:
public class Person extends RealmObject{@PrimaryKey private int id;@必需的私有字符串名称;私有字符串地址;//逗号分隔的字符串,例如“[10,20,30]”私有字符串contactsIds;}
?是的,类似的。这取决于您以后查询它们的方式,因为如果您需要查询
包含
,并且您的ID可以同时包含
10
100
,那么类似
,10100,
的内容更好,因为这样您可以查询
,“+number+”,”
以可靠的方式。这是我经常考虑的,考虑到
RealmList
还不受支持(虽然下一个主要版本将有核心支持,所以它将在几个月后出现)。
E/REALM_JNI( 9018): jni: ThrowingException 8, The following changes cannot be made in additive-only schema mode:
E/REALM_JNI( 9018): - Primary Key for class 'RealmInt' has been added., .
E/REALM_JNI( 9018): Exception has been thrown: The following changes cannot be made in additive-only schema mode:
E/REALM_JNI( 9018): - Primary Key for class 'RealmInt' has been added.
public void fromJsonToRealm(final String someJson) {
    try(Realm realm = Realm.getDefaultInstance()) {
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
               Person person = JsonUtil.gson.fromJson(someJson, Person.class);
               long personId = person.getId();
               Person managedPerson = realm.where(Person.class).equalTo("id", personId).findFirst();
               if(managedPerson != null) {
                   managedPerson.getContactIds().deleteAllFromRealm();
               }
               realm.copyToRealmOrUpdate(person);
            }
        });
    }
public void fromJsonToRealm(final String someJson) {
    try(Realm realm = Realm.getDefaultInstance()) {
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
               Person person = JsonUtil.gson.fromJson(someJson, Person.class);
               long personId = person.getId();
               Person managedPerson = realm.where(Person.class).equalTo("id", personId).findFirst();
               if(managedPerson != null) {
                   boolean wasFound = false;
                   for(RealmInt existingInt : managedPerson.getContactIds()) {
                       for(RealmInt newInt : person.getContactIds()) {
                           if(existingInt.getValue() == newInt.getValue()) {
                               wasFound = true;
                               break;
                           }
                       }
                       if(!wasFound) {
                           existingInt.deleteFromRealm();
                       }
                   }
                   Iterator<RealmInt> newIntIterator = person.getContactIds().iterator();
                   while(newIntIterator.hasNext()) {
                       RealmInt newInt = newIntIterator.next();
                       boolean wasFound = false;
                       for(RealmInt existingInt : managedPerson.getContactIds()) {
                           if(existingInt.getValue() == newInt.getValue()) {
                               wasFound = true;
                               break;
                           }
                       }
                       if(!wasFound) {
                           newIntIterator.remove();
                       }
                   }
               }
               realm.copyToRealmOrUpdate(person);
            }
        });
    }