Search code examples
javaandroidrealm

Error Performing an update in Realm


I am trying to update a property inside my RelamObject(RealmCase in this case). I have tried the code below and it looks like nothing is updated in my Realm although I do see a new object in the RealmPatientInfo Table, there is just no relationship created from my RealmCase.

    RealmCase realmCase = new RealmCase();
    realmCase.setId(getId());
    realmCase.setPatientInfo(new RealmPatientInfo(patientInfo));
    Realm realm = Realm.getDefaultInstance();
    realm.beginTransaction();
    realm.copyToRealmOrUpdate(realmCase);
    realm.commitTransaction();
    realm.close();

I have also tried the following but get an exception saying the value is not managed by realm.

    Realm realm = Realm.getDefaultInstance();
    realm.beginTransaction();
    RealmQuery<RealmCase> query = realm.where(RealmCase.class);
    RealmCase persistedCase = query.findFirst();
    persistedCase.setPatientInfo(new RealmPatientInfo(patientInfo));
    realm.copyToRealmOrUpdate(realmCase);
    realm.commitTransaction();
    realm.close();

I also want to remove the old patientInfo object(both the reference and the entry in the RealmPatientInfo table) Below is my attempt at that, although my error from before has prevented me from testing that part.

        Realm realm = Realm.getDefaultInstance();
        realm.beginTransaction();
        RealmQuery<RealmCase> query = realm.where(RealmCase.class);
        RealmCase persistedCase = query.findFirst();
        if(persistedCase.getPatientInfo() != null) {
            persistedCase.getPatientInfo().removeFromRealm();
            persistedCase.setPatientInfo(null);
        }

        persistedCase.setPatientInfo(new RealmPatientInfo(patientInfo));
        realm.copyToRealmOrUpdate(realmCase);
        realm.commitTransaction();
        realm.close();

Any advice is greatly appreciated.


Solution

  • If you want to replace the PatientInfo object in a RealmCase while making sure the old object is properly deleted you can do the following:

    Realm realm = null;
    try {
        realm = Realm.getDefaultInstance();
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) { 
                RealmQuery<RealmCase> query = realm.where(RealmCase.class);
                RealmCase persistedCase = query.findFirst();
                PatientInfo oldPatientInfo = persistedCase.getPatientInfo();
                if(oldPatientInfo != null) {
                    oldPatientInfo.removeFromRealm();
                }
    
                // New Objects either have to be copied first or created using createObject
                PatientInfo newPatientInfo = realm.copyToRealm(new RealmPatientInfo(patientInfo));
                persistedCase.setPatientInfo(newPatientInfo);
            }
        });
    } finally {
        if(realm != null) {
           realm.close();
        }
    }
    

    Right now you have to manually delete the old PatientInfo, with cascading deletes that can happen automatically instead: https://github.com/realm/realm-java/issues/1104

    Also, e.g. RealmList supports copying objects automatically to Realm when using list.add(item), setting properties like setPatientInfo require the object to be persisted first. This is probably something we should revisit so the behaviour is more consistent. It would also have meant that your first code sample would have worked.