今天我们翻译下图显示的目录中的Relationships模块。
这篇翻译所要翻译的内容如下图所示:
任意二个RealmObjects 能够被连接到一起。
public class Email extends RealmObject {
private String address;
private boolean active;
// ... setters 和 getters方法
}
public class Contact extends RealmObject {
private String name;
private Email email;
// ... setters 和 getters 方法
}
这一段大概意思懂,但不知道该怎么直译比较好,一些专业的在数据库中的术语不好直接翻译。请大家帮忙看下。下面评论里回复下。谢谢了 (我是这么翻译的:在Realm中,Relationships 在Realm中是低消耗的。这意味着,建立一个链接在速度方面并不是高消耗,并且relationships的内部展现在内存消耗方面又是高效的。)
Relationships are generally cheap in Realm. This means that following a link is not expensive in terms of speed, and the internal presentation of relationships is highly efficient in terms of memory consumption.
在你的类型为RealmObject子类中定义一个属性,
public class Contact extends RealmObject {
private Email email;
// Other fields…
}
每个contact (Contact
实例) 有 0个或者1个 email (Email
实例)。在Realm中,无法阻止你在不同的contact对象中使用相同的email对象。并且上述的model可以是many-to-one(多对一)的关系。但是经常被用做成为one-to-one(一对一)的关系。
设置RealmObject
为 null
,将会清除引用但是object不会从Realm中删除。
通过object中的 RealmList
字段声明来建立与任何数量的objects之间的关系。举例来说,一个contact会有多个email地址。
public class Contact extends RealmObject {
public String name;
public RealmList emails;
}
public class Email extends RealmObject {
public String address;
public boolean active;
}
RealmList
s 主要包含RealmObject
s,并且RealmList
表现的很像Java的List
。在Realm中,对于一个相同的object 在不同的RealmList
s中被使用了二次(或者更多)并不进行限制。因此你能对model使用one-to-many(一对多)和many-to-many(多对多)关系。
你能创建objects ,并且使用RealmList.add()
来给Contact
对象添加Email
对象。
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 = "john@example.com";
email1.active = true;
contact.emails.add(email1);
Email email2 = realm.createObject(Email.class);
email2.address = "jd@example.com";
email2.active = false;
contact.emails.add(email2);
}
});
当在给确定的数据类型建立模型的时候,进行声明递归关系会显得有用。
public class Person extends RealmObject {
public String name;
public RealmList friends;
// Other fields…
}
将RealmList
字段的值设置为null
后会清空list。就是说list将会变空(长度为0),但是没有objects被删除,RealmList
的getter方法获取永远不会为null
。返回的objects总是为list,但是长度可能是0。
有可能需要查询链接或关系,细想下面的这个model:
public class Person extends RealmObject {
private String id;
private String name;
private RealmList dogs;
// getters and setters
}
public class Dog extends RealmObject {
private String id;
private String name;
private String color;
// getters and setters
}
如这个图所示:每个Person
对象会有多个dog的关系。
让我们来通过链接查询找到一些person。
// persons => [U1,U2]
RealmResults persons = realm.where(Person.class)
.equalTo("dogs.color", "Brown")
.findAll();
首先,注意到equalTo
里面的字段包含了关系对应的方式(通过.
分割)。
上面的查询可以这么理解:查询出所有的人,而且这些人都有着颜色为“Brown”的狗。重要的是要懂的:这些搜出来的Person object中也会包含那些不满足条件的Dog
objects。因为这些不满足的Dog objects 也是Person
’s object的一部分。
persons.get(0).getDogs(); // => [A,B]
persons.get(1).getDogs(); // => [B,C,D]
这可以通过以下两个查询进一步检查。
// r1 => [U1,U2]
RealmResults r1 = realm.where(Person.class)
.equalTo("dogs.name", "Fluffy")
.findAll();
// r2 => [U1,U2]
RealmResults r2 = r1.where()
.equalTo("dogs.color", "Brown")
.findAll();
注意到第一个查询返回了二个Person objects ,因为这二个persons 符合条件,查询到的结果中每个Person都包含着一系列的Dog objects(是他们所拥有的所有的狗,即使有些狗不满足查询时候的条件)。记住,我们搜索的是拥有特定种类的狗(狗的名字和狗的颜色)的那些人。而不是去搜这些特定的狗。因此,第二个查询也将与第一个查询的Person(r1)及这些Person的dogs也一样。这些人也都符合第二次查询的条件,只是这次是通过狗的颜色来查询的。
让我们再深入一点了解情况,帮助巩固这个概念。请看下面的例子:
// r1 => [U1,U2]
RealmResults r1 = realm.where(Person.class)
.equalTo("dogs.name", "Fluffy")
.equalTo("dogs.color", "Brown")
.findAll();
// r2 => [U2]
RealmResults r2 = realm.where(Person.class)
.equalTo("dogs.name", "Fluffy")
.findAll()
.where()
.equalTo("dogs.color", "Brown")
.findAll();
.where()
.equalTo("dogs.color", "Yellow")
.findAll();
第一个查询可以这么理解:分别查找拥有名叫Fluffy小狗的所有Persons及查找拥有小狗颜色为Brown的所有Persons。然后对二者所查到的Persons取交集。 第二个查询可以这么理解:查找拥有名字叫Fluffy小狗的所有Persons。然后在该结果集中继续查找拥有颜色为“Brown”小狗的所有Persons,然后再在该结果集中继续查找拥有颜色为“Yellow”的所有Persons。
让我们详细了解下 r1
这个结果的背后到底发生了什么。二个条件分别是equalTo("dogs.name", "Fluffy")
和 equalTo("dogs.color", "Brown")
。满足第一个条件的是U1和U2(记这个结果集为C1)。满足第二个条件的是U1和U2(记这个结果集为C2)。在查询中的‘与’逻辑操作相当于对C1和C2的交集。而C1和C2的交集就是U1和U2,所以r1就是U1和U2.
第二个查询的结果r2是不同的。首先第一部分的查询就像是这样:ealmResults r2a = realm.where(Person.class).equalTo("dogs.name", "Fluffy").findAll();
符合的条件:U1和U2。然后r2b = r2a.where().equalTo("dogs.color", "Brown").findAll();
同样符合的是U1和U2(所有的人都有brown dogs),最后的查询是r2 = r2b.where().equalTo("dogs.color", "Yellow").findAll();
。符合的只有U2,由于在brown dog 的结果集中只有一个person有 Yesllow dog,即U2。