1 概述
Isar是专门为Flutter打造的跨平台数据库(当前版本不支持web),支持ACID语义、全文搜索、复合索引和多条目索引等功能,单个NoSQL数据库实例即能支持存入数十万的数据并能保证高速的异步查询。
2 安装
pubspec.yaml文件中增加以下引用:
dependencies:
isar:
isar_flutter_libs:
dev_dependencies:
isar_generator:
build_runner:
3 定义表
import 'package:isar/isar.dart';
part 'table.g.dart';
// 类名即表名
@collection
class Email {
Id id = Isar.autoIncrement; // 唯一自增ID;必须字段。
String? title;
DateTime? dateTime;
@Index()
int? attachmentSize; // 索引
// 模拟类嵌套
Recepient? recipient;
}
例如上面的代码table.dart,首先在头部加入part引用代码 part '类名.g.dart'
,这个文件稍后我们会通过代码生成器(build_runner)来生成。例如定义一个类Email,在类名上面增加@collection
标记,这个类名就是数据库的表名。支持类的嵌套使用,被嵌套的类需要在类名上增加@embedded
标记。
表定义完后(以及当以后再修改时),在控制台中运行以下命令生成该表的代码文件,例如table.g.dart。
flutter pub run build_runner build
4 基本使用
这里简单介绍基本的代码,详细请参考官方文档:https://isar.dev/zh/tutorials/quickstart.html
本文的全部示例代码:https://github.com/tilongzs/flutter_study_demo/tree/master/database_isar_test
4.1 打开数据库
late Isar _isar; // Isar 实例
void openDB() async{
final dir = "D:/";
_isar = await Isar.open(
[EmailSchema],
directory: dir,
name: 'testdb'
);
if(_isar == null){
print('数据库打开失败');
}else{
print('数据库打开成功');
}
}
在Windows平台执行后会在D盘生成testdb.isar数据库文件。
4.2 增
Future<int> add() async{
// 创建一行数据
final newEmail = Email();
newEmail.title = '邮件标题';
final recipient = Recepient();
recipient.name = 'mengmei';
recipient.address = 'mm@mengmei.moe';
newEmail.recipient = recipient;
// 存入数据库
await _isar.writeTxn(() async { // 读写操作的代码必须放置在isar.writeTxn()中
_currentEmailID = await _isar.emails.put(newEmail);
print('新增一行数据 id:${newEmail.id}');
});
return _currentEmailID;
}
新增的一行数据使用唯一id标识该行数据,之后对该行数据的修改、删除等操作均使用该id。注意对数据的操作需要放置在isar.writeTxn()
中。
4.3 删
删除一行数据
Future<bool> delete() async{
if(_currentEmailID != 0){
var ret = false;
await _isar.writeTxn(() async { // 读写操作的代码必须放置在isar.writeTxn()中
ret = await _isar.emails.delete(_currentEmailID);
print('删除一行数据 id:$_currentEmailID ${ret}');
});
return ret;
}
print('先增加数据');
return true;
}
清空表
Future<void> clear() async{
await _isar.writeTxn(() async { // 写操作的代码必须放置在isar.writeTxn()中
_isar.emails.clear();
print('清空表');
});
}
删除所有表
Future<void> deleteAllData() async{
await _isar.writeTxn(() async { // 写操作的代码必须放置在isar.writeTxn()中
_isar.clear();
print('删除所有表');
});
}
4.4 改
Future<void> modify() async{
// 使用唯一id查找数据
final existingEmail = await _isar.emails.get(_currentEmailID);
if(existingEmail == null){
print('没有找到数据 id:$_currentEmailID');
}else{
// 修改数据
existingEmail.title = '修改后的数据';
existingEmail.dateTime = DateTime.now();
await _isar.writeTxn(() async { // 写操作的代码必须放置在isar.writeTxn()中
_currentEmailID = await _isar.emails.put(existingEmail);
print('修改一行数据 id:$_currentEmailID title.title=${existingEmail.title} datetime:${existingEmail.dateTime}');
});
}
}
4.5 查
使用唯一id查找数据
void find() async{
if(_currentEmailID != 0){
// 使用唯一id查找数据
final existingEmail = await _isar.emails.get(_currentEmailID);
if(existingEmail == null){
print('没有找到数据 id:$_currentEmailID');
}else{
print('找到数据 id:$_currentEmailID title:${existingEmail.title} datetime:${existingEmail.dateTime}');
}
return;
}
print('先增加数据');
}
使用索引查询where() https://isar.dev/zh/queries.html#where-%E5%AD%90%E5%8F%A5
void whereAttachmentSize() async{
final result = await _isar.emails.where().attachmentSizeEqualTo(2).findAll();
print('查找附件大小为2的所有数据 共${result.length}个');
result.forEach((e) {
print('查找到数据 id:${e.id} datetime:${e.dateTime}');
});
}
使用非索引查询filter() https://isar.dev/zh/queries.html#filter
void filterDatetime() async{
final result = await _isar.emails.filter().dateTimeLessThan(DateTime.now()).findAll();
print('查找比当前时间小的所有数据 共${result.length}个');
result.forEach((e) {
print('查找到数据 id:${e.id} datetime:${e.dateTime}');
});
}