Realm一对多及多对多反向连接查询

Realm backlinks, queries to linking objects, and changes in schema design

In Realm Android 3.4.0-SNAPSHOT, support for queries across backlinks got merged, and with the next release, inverse relations will be out of beta.

This allows us to simplify the Realm schema by replacing many bi-directional links with uni-directional ones, and replace the links “pointing back” with backlinks.


Realm反连接,查询连接的对象及schema设计中的改变

在Realm的Android 3.4.0-尝鲜版中,已合并对反向连接交叉查询的支持,在下一个发布版本中,反向关系将正式可用。

使用单向连接替换众多双向连接,并用反向连接替换“指向”连接,这允许我们简化Realm数据库。


@LinkingObjects
The support for inverse relations was initially added in 3.1.0, but it didn’t support queries across them until now. This essentially means that for any relation you have in your schema (either 0..1 or 0..*), you can now see the objects that are linking to your current object.
For example, we have the following model classes:

@连接对象

最初是在3.1.0中增加对反向关系的支持,但是直到目前还不支持它们之间的交叉查询。本质上是说,在数据库中的任何关系(或者是0..1,或者是0..x),你能看到连接到当前对象的对象们。如,我们有以下模型类:

public class Dog extends RealmObject {
    @PrimaryKey
    private String id;
  
    private int age;
  
    // getters, setters
}

public class Person extends RealmObject {
    @PrimaryKey
    private String id;
  
    private String name;
  
    // getters, setters
}

And what we want to specify is that a Person can have multiple dogs. Let’s say that a Dog can only be owned by one person. Previously, you would have to create the following schema:

我们想说的是,一个人能有好几只狗。又比如一个狗只能有一个主人。以前,你得创建如下数据图:

public class Dog extends RealmObject {
    @PrimaryKey
    private String id;
  
    private int age;
  
    private Person owner; // <--- !!!
    
    // getters, setters
}

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

// creating objects
r.executeTransaction((realm) -> {
    Dog dog = realm.createObject(Dog.class, "dogId");
    Person person = realm.createObject(Person.class, "personId");
    person.getDogs().add(dog);
    dog.setOwner(person); // <--- !!!
});

// link query
RealmResults<Dog> dogs = realm.where(Dog.class)
                              .equalTo("owner.name", "Jack")
                              .findAll();

And while a Dog is technically owned by a Person, we don’t really need to say that a “Dog belongs to a Person”, right?
We say the Person owns the Dog. Then we implicitly know that the Dog is owned by that given Person.
This is an inverse relationship: if a Person owns a Dog, then that Dog is owned by that Person.

We can now replace manually established bi-directional links, with automatically managed backlinks to linking objects.


准确来说,当一只狗被一个人拥有时,我们不必说“狗属于一个人”,对吧?

我们说人拥有狗,隐含的意思是狗被指定的人拥有。

这是一个反向关系:如果一个人拥有一只狗,那么那么那只狗被那个人拥有。

现在,对于连接对象,我们能使用可管理反向连接来替换手动建立的双向连接。

public class Dog extends RealmObject {
    @PrimaryKey
    private String id;
  
    private int age;
  
    @LinkingObjects("dogs") // <-- !
    private final RealmResults<Person> owners = null; // <-- !
    
    // getters, setters
}

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

// creating objects
r.executeTransaction((realm) -> {
    Dog dog = realm.createObject(Dog.class, "dogId");
    Person person = realm.createObject(Person.class, "personId");
    person.getDogs().add(dog);
    // dog.getOwners() will automatically contain `person`
});

// link query
RealmResults<Dog> dogs = realm.where(Dog.class)
                              .equalTo("owners.name", "Jack")
                              .findAll();

Every relationship, either 0..1 or 0..* creates their corresponding backlinks in the target class.
One thing to note is that an inverse relationship can only be seen as 0..* meaning it must be declared as RealmResults<T>. Also, when declared, it is final and the accessors are transformed to return the managed linking objects.
With that, we no longer need to manually manage the owners of the Dog, it’s managed by Realm automatically :)

What’s worth a mention is that backlink fields don’t need to be added with migration, but if you remove the list or property that points back, then of course a migration is needed to remove that field.


每一个关系,不管是0..1还是0..*,都在目标类中创建它们对应的反向连接。

要注意一个事情,一个反向关系只能被视作0..*,意思是它必须被声明为 RealmResults<T>。当定义它时,应使用final修饰,而且访问符被转变以返回可管理连接对象。

有了它,我们不必再手动管理狗的拥有者,它被Realm自动管理了。 :)

值得提出的是,反向连接字段在增加时不需要迁移,但是如果你移除此list或指回的属性,则当然需要一个迁移来移除字段。(注:意思是说,增加连接字段不会改变表结构,不用做数据迁移,但是删除它则需要做


Conclusion
Automatic inverse relations will simplify Realm schema design, and schema maintenance. Hopefully this article gave you a quickstart for how to work with @LinkingObjects.


结论

自动反向关系将简化Realm数据结构设计和数据结构维护。本文希望给你一个快速指导:怎样使用@LinkingObjects进行工作?

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值