syfy syfy - 19 days ago 6
Android Question

How structure a realm database without instantiating variables with null in one-to-one mapping?

How would I structure my Realm database if the user had an option to input one of 4 fields: a,b,c,d.

Currently I've created one RealmObject model class with all of the getters and setters in one class, so if a user adds to c, the output looks like this:

[modelClassName = [{a:null},{b:null},{c:6664},{d:null}]]


Is this the best way to go about it? Or should I be creating a model class for each variable? The latter seems like an overkill.

Answer

As mentioned in my article Designing the Schema of Realm effectively, you can store the fields in one "table", and store an additional discriminator field that determines which field is currently valid to read from.

So in your case,

public class Something extends RealmObject {
    public static final String TYPE_A = "a";
    public static final String TYPE_B = "b";
    public static final String TYPE_C = "c";
    public static final String TYPE_D = "d";

    private String a;
    private String b;
    private String c;
    private String d;

    @Index
    private String discriminator;

    public String getA() {
        return a;
    }

    public String getB() {
        return b;
    }

    public String getC() {
        return c;
    }

    public String getD() {
        return d;
    }

    public void setA(String a) {
        this.a = a;
        this.b = null;
        this.c = null;
        this.d = null;
        this.discriminator = TYPE_A;
    }

    public void setB(String b) {
        this.a = null;
        this.b = b;
        this.c = null;
        this.d = null;
        this.discriminator = TYPE_B;
    }

    public void setC(String c) {
        this.a = null;
        this.b = null;
        this.c = c;
        this.d = null;
        this.discriminator = TYPE_C;
    }

    public void setD(String d) {
        this.a = null;
        this.b = null;
        this.c = null;
        this.d = d;
        this.discriminator = TYPE_D;
    }
}

Or something like that. Additional validation or some unified getValue() method can be added, the types can be represented by an enum instead (and the enum's name() could be stored in the Realm), etc.

In fact, if you want, you can even just merge all a, b, c, d fields into 1 field called `value, and also keep the discriminator.

public class Something extends RealmObject {
    public static final String TYPE_A = "a";
    public static final String TYPE_B = "b";
    public static final String TYPE_C = "c";
    public static final String TYPE_D = "d";

    @Index
    private String discriminator;

    private String value;

    // getters, setters

    public void setA(String a) {
        this.value = a;
        this.discriminator = TYPE_A;
    }

    public void setB(String b) {
        this.value = b;
        this.discriminator = TYPE_B;
    }

    public void setC(String c) {
        this.value = c;
        this.discriminator = TYPE_C;
    }

    public void setD(String d) {
        this.value = d;
        this.discriminator = TYPE_D;
    }
}

It's up to you, really.


This answer is applicable for Realm 0.88.0+