[官文翻译]Futter超快数据库Isar - 概念 - 链接
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()
。
在内部 IsarLink
和 IsarLinks
以相同的方式表现。
这使我们可以从之前的 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