likes
comments
collection
share

[官文翻译]Futter超快数据库Isar - 概念 - 链接

作者站长头像
站长
· 阅读数 54

Isar:用于 Futter 可跨平台的超快数据库

官方文档:Home | Isar Database

pub:isar | Dart Package (flutter-io.cn)

本文翻译自:Links | Isar Database

译时版本:3.0.2


链接

链接可以表现对象之间的关系,如 评论的作者(用户)。 使用 Isar 的链接可以表现 1对1,1对多,多对多。 相比 嵌入对象,使用 链接 有些不符合常规思维,如果可能的话,应该使用嵌入对象。

可以认为链接是包含关联关系的一个单独的表。 它类似于 SQL 的连接,但是有不同的特性集和 API 。

IsarLink

IsarLink<T> 能够包含 0 个或一个关联的对象,所以它可以用来表现 对1 的关系。 IsarLink 有一个叫作 value 的属性,它保有链接的对象。

链接是延迟加载的,所以需要明确告诉 IsarLink 加载或保存这个 value 。 可调用 linkProperty.load() 和 linkProperty.save() 来实现。

链接来源集合和链接目标集合的 id 属性应该是 不是 final 的。

从非 Web 的目标,链接会在第一次使用它们时自动加载。 让我们开始向集合中添加一个 IsarLink:

@Collection()
class Teacher {
  int? id;

  late String subject;
}

@Collection()
class Student {
  int? id;

  late String name;

  final teachers = IsarLink<Teacher>();
}

我们定义了一个关联 teacher (老师)和 student (学生) 的链接。 该示例中每个学生明确只有一个老师。

首先我们创建一个 teacher 然后指定给一个学生。 正如在示例中看到的,我们需要手动(显式地)put()(添加)某个学生。

final mathTeacher = Teacher()..subject = 'Math';

final linda = Student()
  ..name = 'Linda'
  ..teachers.value = mathTeacher;

await isar.writeTxn((isar) async {
  await isar.students.put(linda);
});

现在我们可以使用该链接:

final linda = await isar.students.where().nameEqualTo('Linda').findFirst();

final teacher = linda.teacher.value; // > Teacher(subject: 'Math')

现在试着用同步代码来做相同的处理。 我们不需要手动保存链接因为 .putSync() 会自动保存所有链接。 它甚至会为我们创建 teacher (老师)。

final englishTeacher = Teacher()..subject = 'English';

final david = Student()
  ..name = 'David'
  ..teacher.value = englishTeacher;

isar.writeTxnSync(() {
  isar.students.putSync(david);
});

IsarLinks

上面示例中,一个学生可以有多个老师会更合理。 幸运的是 Isar 有 IsarLinks<T> ,它能包含多个关联的对象,表现为 对多 的关系。

IsarLinks<T> 继承了 Set<T> ,所以它暴露了所有可用于 set 的方法。

IsarLinks 的行为更像 IsarLink ,也是延迟加载的。 要加载所有关联的对象,可调用 linkProperty.load() 。 要将所有的改变永久化,可调用 linkProperty.save()

在内部 IsarLinkIsarLinks 以相同的方式表现。 这使我们可以从之前的 IsarLink<Teacher> 升级到 IsarLinks<Teacher> 为单个学生指定多个老师(不会丢失数据)。

@Collection()
class Student {
  int? id;

  late String name;

  final teachers = IsarLinks<Teacher>();
}

这能正常工作是因为我们没有改变链接的名称(teacher),所以 Isar 一开始就会记住该链接。

final biologyTeacher = Teacher()..subject = 'Biology';

final linda = isar.students.where()
  .filter()
  .nameEqualTo('Linda')
  .findFirst();

print(linda.teachers); // {Teacher('Math')}

linda.teachers.add(biologyTeacher);

await isar.writeTxn(() async {
  await linda.teachers.save();
});

print(linda.teachers); // {Teacher('Math'), Teacher('Biology')}

Backlink(反向链接)

我听到你问 "如果想要表现反向的关系该用什么?"。 不用担心,我们现在会介绍反向链接 。

反向链接是反方向的链接。 每个链接都有一个隐式的反向链接 。 要在应用中使其可用,可以用 @Backlink()IsarLink 或 IsarLinks 添加注解。

反向链接无需额外的内存或资源,可以自由添加、移除和重命名而不会丢失数据。

我们想知道某个老师有哪些学生,可以定义一个反向链接:

@Collection()
class Teacher {
  int? id;

  late String subject;

  @Backlink(to: 'teachers')
  final students = IsarLinks<Student>();
}

我们需要为链接指定指向它的反向链接。 在两个对象之间也可以有多个不同的链接。

初始化链接

IsarLink 和 IsarLinks 都有一个无参的构造方法,应该用来在对象被创建时分配链接属性。 将链接属性设置为 final 是好的实践。

首次 put() 对象时,链接会初始化源集合和目标集合,然后可以调用方法、如 load() 和 save() 。链接会在创建后立刻开始跟踪变化,这样就可以添加或移除关联了 甚至在链接初始化之前。

移动链接到另一个对象是违反规则的。


转载自:https://juejin.cn/post/7154227370558226439
评论
请登录