【译】ObjectBox官方文档(4)——关系

转载请注明出处 第一次翻译文档,水平有限,如有任何错误和不妥,望指正。此外如想知道与RealmGreenDAO的对比请查看这篇博客 官网:ObjectBox 官方示例:Github

在对象中可以引用其他对象,例如,简单的引用对象或者引用一个 List 对象,在数据库术语中,我们称这些引用 关系 。定义关系的对象我们称其为 源对象,我们把引用的对象称之为 目标对象,所以这个关系是有指向性的。

To-One关系

使用 ToOne类定义 To-One 关系,它是一个针对目标对象的智能代理,会透明地缓存目标对象(?)。例如,一个订单通常由一个客户完成。我们可以对订单类( Order)进行建模并与客户( Customer)建立一个一对一关系:

// Customer.java
@Entity
public class Customer {
 
    @Id public long id;
 
}
 
 
// Order.java
@Entity
public class Order {
 
    @Id public long id;
 
    public ToOne<Customer> customer;
 
}
复制代码

现在让我们添加一个客户和一些订单。需要设置相关的 customer 对象,在ToOne实例上调用setTarget()并放置 order 对象:

Customer customer = new Customer();
Order order = new Order();
order.customer.setTarget(customer);
long orderId = boxStore.boxFor(Order.class).put(order); // puts order and customer
复制代码

如果 customer 对象在数据库中还不存在,则 ToOne 将创建并插入它。有关更新关系的细节,请参阅下面的详细信息。

想要获取订单的客户,需要调用 ToOnegetTarget()方法:

Order order = boxStore.boxFor(Order.class).get(orderId);
Customer customer = order.customer.getTarget(customer);
复制代码

它使用 ID 进行查找,这在 ObjectBox 中非常快。如果您只需要 ID 而不是整个目标对象,那么就调用getTargetId()。它可以更高效,因为它根本不涉及数据库。

我们也可以将客户关系移除:

order.customer.setTarget(null);
boxStore.boxFor(Order.class).put(order);
复制代码

注意,这并没有将客户从数据库中删除,它只是将关系分解。

Initialization Magic

您是否注意到在上面的代码示例中,ToOne 字段customer从未被初始化?为什么代码仍然可以使用customer而没有任何NullPointerException?因为字段实际上是初始化的,初始化代码在您的源代码中是不可见的。

ObjectBox gradle 插件将在您的代码执行之前转换您的实体类,以便在构造函数中进行适当的初始化。因此,即使在构造函数代码中,您也可以假设 ToOneToMany / List 属性已经被初始化,并且已经准备好使用了。

To-Many关系

要定义一个 To-Many 关系,您可以使用类型 ListToMany 类的属性。由于只有 ToOne 类, ToMany 类可以帮助您跟踪更改并将这些更改应用到数据库中。如果您不需要或不想要这些,请使用 List 类型,并自己处理数据库更改。

One-to-Many (1:N)一对多关系

要定义一对多关系,您需要用 @backlink来注释您的关系属性。它连接到目标对象中的一个 To-One 关系。使用客户和订单的例子,我们可以修改客户( Customer)类,使其与订单( Order)有许多关系:

// Customer.java
@Entity
public class Customer {
 
    @Id public long id;
 
    @Backlink
    public ToMany<Order> orders;
 
}
 
// Order.java
@Entity
public class Order {
 
    @Id public long id;
 
    public ToOne<Customer> customer;
 
}
复制代码

@backlink注释告诉 ObjectBox 它的 ToOne 关系,用于填充订单列表。如果在 Order 类中与多个客户存在关系,您需要显式地指定@backlink(to="Customer")的名称。

让我们给新客户添加一些订单。ToMany 实现了 Java List 接口,因此我们可以简单地使用它添加:

Customer customer = new Customer();
customer.orders.add(new Order());
customer.orders.add(new Order());
long customerId = boxStore.boxFor(Customer.class).put(customer); // puts customer and orders
复制代码

通过访问订单列表,我们可以轻松地获得客户的订单:

Customer customer = boxStore.boxFor(Customer.class).get(customerId);
for (Order order : customer.orders) {
    // TODO
}
复制代码

remove 与之前一样:

Order order = customer.orders.remove(0);
boxStore.boxFor(Customer.class).put(customer);
// optional: 也可以从它的Box中删除订单
// boxStore.boxFor(Order.class).remove(order);
复制代码

Many-to-Many (N:M)多对多关系

要定义多对多关系,只需使用 ToMany 类添加属性。假设学生和老师的例子,这就是一个与很多老师有关系的简单的学生类的例子(( ̄ェ ̄;)):

// Teacher.java
@Entity
public class Teacher{
 
    @Id public long id;
 
}
 
// Student.java
@Entity
public class Student{
 
    @Id public long id;
 
    public ToMany<Teacher> teachers;
 
}
复制代码

为学生添加老师就像操作一个列表:

Teacher teacher1 = new Teacher();
Teacher teacher2 = new Teacher();
 
Student student1 = new Student();
student1.teachers.add(teacher1);
student1.teachers.add(teacher2);
 
Student student2 = new Student();
student2.teachers.add(teacher2);
 
// puts students and teachers
boxStore.boxFor(Student.class).put(student1, student2);
复制代码

为了得到一个学生的老师,我们只需要访问这个列表:

Student student1 = boxStore.boxFor(Student.class).get(student1.id);
for (Teacher teacher : student1.teachers) {
    // TODO
}
复制代码

如果一个学生离开了课堂,我们可以移除一位老师:

student1.teachers.remove(0);
// boxStore.boxFor(Student.class).put(student1);
// 比put更有效率:
student1.teachers.applyChangesToDb();
复制代码

更新关系

ToOne和ToMany类可以帮助您维护关系的状态。一旦您的实体拥有了关系,它们将跟踪更改并将更改应用到数据库中。ObjectBox 支持对新版本的关系更新(尚未持久化; ID 为零)和现有的(持久化的; ID 不是零)的实体。

更新 To-One

ToOne 类提供了以下方法来更新关系:

  • setTarget(entity):设置实体(新的或者已存在)为新的关系目标,传null即清除关系
  • setTargetId(entityId):设置与给定 Id 的目标实体的关系;通过0来清除关系
order.customer.setTarget(customer); // or order.customer.setCustomerId(customer.getId());
orderBox.put(order);
复制代码

更新 To-Many

ToMany 类实现java.lang.List接口,同时为实体添加更改跟踪。如果要向 ToMany 对象添加实体,那么这些实体对象将被放在数据库中。同样地,您也可以将实体从 ToMany 对象中移除。注意,从列表中删除实体实际上并没有从数据库中删除实体;只是关系被清除了。不要忘记将拥有的实体应用到数据库中,以对数据库进行跟踪。

customer.orders.add(order1);
customer.orders.remove(order2);
customerBox.put(customer);
复制代码

如果您已经设置了@Id(assignable = true)并将 ID 设置为尚未添加的源实体,那么将实体添加到或从 ToMany 移除实体将会失败。作为一种变通方法,您可以在修改 ToManys 之前,通过调用customerbox.attach(customer)(在上面的示例中的第1行之前)来修改这个实体。

树状关系

你可以对树状关系进行建模,使用To-One,To-Many的关系指向它自身:

@Entity
public class TreeNode {
    @Id long id;
 
    ToOne<TreeNode> parent;
 
    @BackLink
    ToMany<TreeNode> children;
}
复制代码

生成的实体可以让您导航它的父类和子类:

TreeNode parent = entity.parent.getTarget();
List<TreeNode> children = entity.children;
复制代码

转载于:https://juejin.im/post/5a31d253f265da431b6d3656

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值