持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
Isar:用于 Futter 可跨平台的超快数据库
官方文档:Home | Isar Database
pub:isar | Dart Package (flutter-io.cn)
本文翻译自:Schema | Isar Database
译时版本:3.0.2
Schema
使用 Isar 时,就是在操作集合。一个集合只能包含单个类型的 Dart 对象。
要让 Isar 知道你想要存储的对象,需要用 @Collection() 注解你的类。 Isar 代码生成器会做剩余的工作。所有绑定的命令称作 "数据库 schema" (数据库模式)。
注解类
Isar 生成器会查找所有用 @Collection() 注解的类。
@Collection()
class Contact {
@Id()
int? id;
String firstName;
String lastName;
bool isStarred;
}
| 配置 | 说明 |
|---|---|
inheritance | 控制父类的字段和混入是否在 Isar 中存储。默认是可以。 |
accessor | 允许重命名默认的集合存取器(例如, isar.contacts 用于 Contact 集合)。 |
ignore | 允许忽略特定的属性。对于父类也会遵守。 |
[Isar Id]
所有的模型类需要定义一个类型为 Id 的id属性,它可唯一标识一个对象。
Id 只是 int 的别名,它使 Isar 生成器可以识别 id 属性。
@collection
class Contact {
Id? id;
String? firstName;
String? lastName;
bool? isStarred;
}
Isar 会自动为 id 字段添加索引,这可以使你高效地读取和修改基于 id 的对象。
也可以自己设定 id 或者要求 Isar 指定一个自增的 id 。如果 id 字段为 null,并且不是 final ,Isar 会指定一个自增的 id 。如果想要一个非空的自增 id 。 你可以使用 Isar.autoIncrement 代替 null 。
自增的 id 在对象被删除后不会再使用。 重置自增 id 的唯一方式是 清空数据库。
重命名类和字段
有时候,用和 Dart 类或字段名不同的名字存储类或字段很有用。
这可以通过为 类或字段添加 Name 属性实现。
下面的集合和上面的 Contact 类存储了同样的内容。
@collection
@Name("Contact")
class MyContactClass1 {
@Name("id")
Id myObjectId;
@Name("firstName")
String theFirstName;
@Name("lastName")
String familyNameOrWhatever;
bool isStarred;
}
特别是如果 你想重命名已经存储到数据库里的字段或类,就该考虑使用 @Name 注解。
否则,数据库只会删除和重新创建字段或集合。
支持的类型
Isar 支持以下数据类型:
boolintdoubleDateTimeStringList<bool>List<int>List<double>List<DateTime>List<String>
另外,也支持嵌入的对象和枚举。会在下面介绍这些。
字节(byte)、短整型(short)、浮点型(float)
对于很多使用场景,不需要完整的64位整型或 double 。 Isar 支持附加的类型,可在排序小一些的数字时节省空间和内存。
| 类型 | 字节数 | 范围 |
|---|---|---|
| byte | 1 | 0 到 255 |
| short | 4 | -2,147,483,647 到 2,147,483,647 |
| int | 8 | -9,223,372,036,854,775,807 到 9,223,372,036,854,775,807 |
| float | 4 | -3.4e38 到 3.4e38 |
| double | 8 | -1.7e308 到 1.7e308 |
附加的数字类型都是原生 Dart 类型的别名,所以例如使用 short 和 使用 int 作用一样。
这里有一个示例集合,包含上面所有的类型:
@collection
class TestCollection {
Id? id;
late byte byteValue;
short? shortValue;
int? intValue;
float? floatValue;
double? doubleValue;
}
所有这些类型都可以用于列表。例如,存储字节应该使用 List<byte> 。
可空类型
理解可空在 Isar 中如何使用很重要:Number 类型没有专用的 null 表现。取而代之的是会使用一个指定的值:
| 类型 | VM |
|---|---|
| short | -2147483648 |
| int | int.MIN |
| float | double.NaN |
| double | double.NaN |
bool 、 String 和 List 都有各自的 null 表现。
这种行为可用于改善性能,并且可以让你自由地修改字段的可空性而不需要迁移或者指定的代码来处理 null 。
byte(字节)类型不支持空值。
DateTime
Isar 不会存储日期的时区信息。
取而代之的是,在存储之前,将 DateTime 转换为 UTC 。
Isar 用本地时区返回所有的日期。
DateTime 使用精度到微秒来存储。
在浏览器上,因为 JavaScript 的限制,只支持精度到毫秒。
枚举
Isar 可以和其它类型一样,存储和使用枚举类型。 你需要选择枚举如何在磁盘上表现。 Isar 支持四种不同的策略:
| 枚举类型 | 描述 |
|---|---|
ordinal | 枚举的索引存储为 byte(字节)。这样很高效,但是不允许空的枚举 |
ordinal32 | 枚举的索引存储为 short (4个字节的整数)。 |
name | 枚举的名称存储为 String(字符串)。 |
value | 自定义属性用于获取枚举值。 |
ordinal 和 ordinal32 依赖枚举值的顺序。
如果改变了顺序,现有的数据库会返回不正确的值。
我们看一个用于不同策略的示例。
@collection
class EnumCollection {
Id? id;
@enumerated // 和 EnumType.ordinal 相同
late TestEnum byteIndex; // 不可为空
@Enumerated(EnumType.ordinal)
late TestEnum byteIndex2; // 不可为空
@Enumerated(EnumType.ordinal32)
TestEnum? shortIndex;
@Enumerated(EnumType.name)
TestEnum? name;
@Enumerated(EnumType.value, 'myValue')
TestEnum? myValue;
}
enum TestEnum {
first(10),
second(100),
third(1000);
const TestEnum(this.myValue);
final short myValue;
}
当然,枚举也可用于列表。
嵌入对象
在集合模型中带有嵌套的对象很有用处。 这里对于嵌套的深度没有限制。 要记住无论要更新的是多深的嵌套对象,都需要向数据库中写入整个对象树。
@collection
class Email {
Id? id;
String? title;
Recepient? recipient;
}
@embedded
class Recepient {
String? name;
String? address;
}
嵌入对象可为空和继承其他对象。
唯一需要的是用 @embedded 注解,并且有一个不带参数的默认构造函数。