Realm(Java)数据库使用文档(Relationships)


Realm(Java)数据库使用文档(目录)

您可以将任何两个RealmObject链接在一起。在Realm中关系很轻便:遍历链接在速度或内存方面并不占用过多资源。让我们探索一下Realm允许您在对象之间进行定义的不同类型的关系。

5.1 多对一

要建立“多对一”或“一对一”关系,请给model一个属性,其类型是您的RealmObject子类之一:

public class Email extends RealmObject {
    private String address;
    private boolean active;
}

public class Contact extends RealmObject {
    private String name;
    private Email email;
}

Contact bob = realm.createObject(Contact.class);
bob.name = "Bob Newhart";

Email email1 = realm.createObject(Email.class);
email1.address = "[email protected]";

bob.email = email1;

每个联系人具有零个或一个电子邮件实例。没有什么可以阻止您将同一个电子邮件对象与多个联系人一起使用;多对一关系和一对一关系之间的区别取决于您的业务逻辑。

将关系字段设置为null将清除引用:

bob.email = null;

这将删除bob和email1之间的关系,但是email1仍在Realm中。

5.2 多对多

您可以通过RealmList <T>字段声明从单个对象创建与任何数量的对象的关系。 让我们重写示例以支持多个电子邮件地址:

public class Contact extends RealmObject {
    public String name;
    public RealmList<Email> emails;
}

public class Email extends RealmObject {
    public String address;
    public boolean active;
}

RealmLists是RealmObjects的容器;RealmList的行为类似于常规的Java List。您可以在不同的RealmLists中使用同一对象,并且可以使用该对象对“一对多”和“多对多”关系进行建模。

realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        Contact contact = realm.createObject(Contact.class);
        contact.name = "John Doe";

        Email email1 = realm.createObject(Email.class);
        email1.address = "[email protected]";
        email1.active = true;
        contact.emails.add(email1);

        Email email2 = realm.createObject(Email.class);
        email2.address = "[email protected]";
        email2.active = false;
        contact.emails.add(email2);
    }
});

可以声明递归关系,这在对某些类型的数据建模时很有用。

public class Person extends RealmObject {
    public String name;
    public RealmList<Person> friends;
    // 其他字段...
}

将RealmList字段的值设置为null将清除列表。列表将为空(长度为零),但列表中的对象不会从Realm中删除。RealmList的getter永远不会返回null:返回的对象始终是列表。长度可能为零。

5.3 逆关系

关系是单向的。 以Person和Dog这两个类为例:

public class Dog extends RealmObject {
    private String name;
    private int age;
}

public class Person extends RealmObject {
    @PrimaryKey
    private long id;
    private String name;
    private RealmList<Dog> dogs;
}

您可以点击从“人”到“狗”的链接,但是无法从“狗”到其“人”对象。 您可以通过为Dog提供@LinkingObjects注解来解决此问题。

public class Person extends RealmObject {
  private String id;
  private String name;
  private RealmList<Dog> dogs;
  // getters and setters
}

public class Dog extends RealmObject {
  private String id;
  private String name;
  private String color;
  @LinkingObjects("dogs")
  private final RealmResults<Person> owners;
  // getters and setters
}

我们为Dog提供了一个所有者字段,并指定该字段应包含在其dogs字段中具有此Dog对象的所有Person对象。

带注解的字段必须声明为final,并且必须为RealmResults <T>类型,其中T是关系相对端的类型/类。由于关系是多对一或多对多的,因此遵循逆向关系可能会导致0、1或更多对象。

像任何其他RealmResults集一样,您可以查询逆关系。

5.4 基元列表(Lists Of Primitives)

Realm Model类可以包含原始数据类型的列表。 这必须使用RealmList <T>进行建模,其中T可以是以下类型:String, Integer, Boolean, Float, Double, Short, Long, Byte, byte[]Date

public class Person extends RealmObject {
  public String name;
  public RealmList<String> children = new RealmList<>();
}

RealmModel的列表不同,基元列表可以包含空值。如果不允许使用空值,请使用@Required注解:

public class Person extends RealmObject {
  public String name;
  @Required
  public RealmList<String> children = new RealmList<>();
}

基元列表不支持列表列表和查询。

在Realm Java 4.0.0之前,通常使用特殊的Realm <String / Int>类对基元列表进行建模。您可以使用以下迁移代码从此方法迁移到基元列表:

// Model classes
public class RealmString extends RealmObject {
  public String value;
}

public class Person extends RealmObject {
  public String name;
  @Required
  public RealmList<String> children = new RealmList<>();
}

// Migration code
RealmObjectSchema objSchema = realmSchema.get("Person");
objSchema.addRealmListField("children_tmp", String.class)
        .setRequired("children_tmp", true)
        .transform(new RealmObjectSchema.Function() {
            @Override
            public void apply(DynamicRealmObject obj) {
                RealmList<DynamicRealmObject> children = obj.getList("children");
                RealmList<String> migratedChildren = obj.getList("children_tmp", String.class);
                for (DynamicRealmObject child : children) {
                    migratedChildren.add(child.getString("value"));
                }
            }
        })
        .removeField("children")
        .renameField("children_tmp", "children");
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章