ObjectBox[八] 关系

本文详细介绍了ObjectBox中的关系模型,包括一对一和一对多的关系定义、懒加载机制、更新操作以及如何处理树型结构关系。通过示例展示了如何在对象之间创建和管理引用,以及如何在数据库中进行相应的操作。
摘要由CSDN通过智能技术生成

ObjectBox[一] 特性

ObjectBox[二] 教程:如何开始使用ObjectBox

ObjectBox[三] 教程:安装和基础

ObjectBox[四] 数据库持久化之实体注解

ObjectBox[五] 基本操作:查询

ObjectBox[六] 数据监听和RX(Data Observers and Reactive Extensions)

ObjectBox[七] 支持LiveData(Android体系结构组件)

ObjectBox[八] 关系

ObjectBox[九] 数据模型变更

ObjectBox[十] 自定义类型

ObjectBox[十一] 事务

ObjectBox[十二] Meta Model, IDs, and UIDs

ObjectBox[十三] 数据调试


更喜欢看代码,请查看Demo

对象可以引用其他对象,例如包含简单引用或对象列表。在数据库方面,我们称这些引用为关系。定义关系的对象我们称之为源(source)对象,被引用的对象称之为目标(target)对象。所以关系是有方向的。

如果有一个目标对象,我们称之为一对一(to one)。 如果可以有多个目标对象,我们称之为一对多(to many)。关系是懒加载的:目标对象在第一次访问时从数据库中取出。一旦目标对象被获取,它们被缓存以进一步访问。

一对一关系

一对一的关系

您可以使用ToOne 类来定义一对一的关系 。它自动获取目标对象并缓存。例如,一个订单通常由一个客户完成。因此,我们可以将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将插入它。 有关更新关系的详细信息,请参阅下文。
要在订单中获取客户customer需要使用 getTarget()

Order order = boxStore.boxFor(Order.class).get(orderId);
Customer customer = order.customer.getTarget(customer);

第一次get会查询数据库调用(懒加载)。它使用ID查找,在ObjectBox中非常快。如果您只需要ID而不是整个目标对象,请调用 getTargetId()。它可以更有效,因为它根本不查询数据库。

我们也能移除关系。如下代码:

order.customer.setTarget(null);
boxStore.boxFor(Order.class).put(order);

请注意,这不会从数据库中删除customer,它只是消除了关系。

初始化魔法

您是否注意到 ToOne 字段customer在上面的代码示例中从未初始化过?为什么代码仍然可以使用 ,而不会有任何NullPointerException?因为该字段实际上是初始化的 - 初始化代码只是不可见在您的来源。ObjectBox Gradle插件调用实体类的构造函数进行初始化。因此,你可以认为 ToOneToMany / List 属性已经被初始化,并且可以使用。

对多关系

要定义多对多关系,可以使用List类型的属性 或 ToMany 类。作为ToOne类, ToMany 类可帮助您自动更改并将其应用于数据库。如果您不需要,请使用List类型 并自行 处理数据库更改。

请注意, 多对多关系在第一次请求上懒加载,然后缓存在ToMany 对象内的源实体中 。所以随后调用关系的get方法不会查询数据库。

如果您需要一对多(1:N)或多对多(N:M)关系,则会有细微差别。1:N关系就像上面的例子,客户可以有多个订单,但订单只与一个客户有关。一个N:M关系的例子是学生和老师:学生可以由几个老师上课,但老师也可以指导几个学生。

一对多 (1:N):

这里写图片描述


要定义一对多关系,您需要使用@Backlink注解。它链接回目标对象中的一对一关系。使用客户和订单示例,我们可以修改客户类别,以便与客户订单具有一对多关系:

// 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 类中有使用Customer的多对一关系 ,则需要明确指定名称,例如 @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

通过访问Custom,我们可以很容易地获得客户的订单:

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

删除订单:

Order order = customer.orders.remove(0);
boxStore.boxFor(Customer.class).put(customer);
// optional: also remove the order from its box
// boxStore.boxFor(Order.class).remove(order);
多对多关系

这里写图片描述

要定义一个多对多关系,只需使用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);
// more efficient than using put:
student1.teachers.applyChangesToDb();

关系更新

ToOne and ToMany 关键字帮助你维护关系,一旦你把拥有关系的对象put进数据库,所有的变化都会应用到数据库中。
ObjectBox支持新的(尚未持久; ID为零)和现有(在ID之前持久ID是非零)对象的关系更新。

ToOne更新

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

  • setTarget(entity)设置新的目标对象; 传 null 以清除关系
  • setTargetId(entityId) 通过ID设置目标对象为数据库中已经存在的对象; 通过 0(零)清除关系
order.customer.setTarget(customer); // or order.customer.setCustomerId(customer.getId());
orderBox.put(order);
ToMany更新

ToMany类实现了 java.lang.List同时绑定了对象的变更。如果您将对象添加到ToMany关系中,那么这些对象将添加到数据库。类似的,如果你从ToMany关系中删除对象,那么这些对象也从关系中删除掉。请注意,从List中删除对象并没有在数据库中删除; 只是关系被清除了。不要忘记将更改应用到数据库中。

customer.orders.add(order1);
customer.orders.remove(order2);
customerBox.put(customer);

注意:如果你已经设置@Id(assignable = true),这种情况下源对象还没有赋值ID,在一对多关系中增加或删除目标对象会失败。作为一种解决方法,您需要在修改关系之前增加一行代码:

customerBox.attach(customer)
customer.orders.add(order1);
customer.orders.remove(order2);
customerBox.put(customer);
例子:树型结构关系

您可以使用指向自身的to-oneto-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;

原文:http://objectbox.io/documentation/relations/

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值