codezjx
codezjx

Reputation: 9142

Issue in realm relationships: Many-to-One, it creates duplicate objects

Following the official documents guide: Realm Relationships

I tried to write some code of Many-to-One relationship, and I found some things that are not consistent.

Two POJO Contace.java and Email.java are defined as follows:

public class Email extends RealmObject {
    private String address;
    private boolean active;
    // ... setters and getters left out
}

public class Contact extends RealmObject {
    private String name;
    private Email email;
    // ... setters and getters left out
}

Situation 1: Create a normal Email object and assign to different Contact contactA and contactB.

Email email = new Email();
email.setAddress("[email protected]");
email.setActive(true);

Contact contactA = new Contact();
contactA.setName("Bear");
contactA.setEmail(email);

Contact contactB = new Contact();
contactB.setName("Monkey");
contactB.setEmail(email);

realm.beginTransaction();
realm.copyToRealm(contactA);
realm.copyToRealm(contactB);
realm.commitTransaction();

After I call realm.copyToRealm(), two Email objects will be created here. So, when I query Contact from Realm, one Email object will become two different object? I think this is not a Many-to-One relationship anymore, it just become One-to-One relationship. enter image description here

Situation 2: Call realm.createObject() to create a proxy Email object and two proxy Contact object, and assign email to contactA and contactB.

realm.beginTransaction();
Email email = realm.createObject(Email.class);
email.setAddress("[email protected]");
email.setActive(true);

Contact contactA = realm.createObject(Contact.class);
contactA.setName("Bear");
contactA.setEmail(email);

Contact contactB = realm.createObject(Contact.class);
contactB.setName("Monkey");
contactB.setEmail(email);
realm.commitTransaction();

enter image description here Here we can see just one Email object in the table, and that's what I expected, just as described in the document above.

So, why is there no consistency in situation1 and situation2? Is it a bug in situation1? Or am I missing something?

Realm version(s):0.88.3

Android Studio version:2.0

Looking forward to your reply! Thanks!

Upvotes: 2

Views: 937

Answers (2)

codezjx
codezjx

Reputation: 9142

Thanks for beeender's answer here: [issue-2730]

This is the expected behaviour.

In the situation1, the email you set to contactA and contactB is a standalone object which is not managed by Realm. So when you copy it to Realm, Realm has no way to know you mean they are the same object. To solve this, you can add a @PrimaryKey to Email and then use copyToRealmOrUpdate. Realm will try to detect if you mean the same email object for both contactA and contactB based on the primary key.

In the situation2, since the email object is managed by Realm, when you call setters, Realm knows that email is actually the same one.

Finally I set a @PrimaryKey both in Contact and Email, as following:

public class Email extends RealmObject {
    @PrimaryKey
    private String address;
    private boolean active;
    // ... setters and getters left out
}

public class Contact extends RealmObject {
    @PrimaryKey
    private String name;
    private Email email;
    // ... setters and getters left out
}

Then change copyToRealm() to copyToRealmOrUpdate() on contactA and contactB.

realm.beginTransaction();
realm.copyToRealmOrUpdate(contactA);
realm.copyToRealmOrUpdate(contactB);
realm.commitTransaction();

And the relationships betweens Contact and Email was correctly in situation 1.

Upvotes: 1

Nongthonbam Tonthoi
Nongthonbam Tonthoi

Reputation: 12953

In the first case two email is created because you are doing copyToRealm two times on different instance.

From the docs Each contact (instance of Contact) have either 0 or 1 email (instance of Email)

Upvotes: 0

Related Questions