Flutter数据库sqlite插件drift和floor选型和切换方案
- 
基本概述
- 
数据操作插件
drift地址: pub.dev/packages/dr…
floor地址: pub.dev/packages/fl…
- 
插件定位
两者的底层均是sqlite数据库,中间层是sqlite3,它们主要操作的是上层的CURD
- 
官方数据对比
- 
pub热度对比:


| 更新日期 | 点赞数 | 评分 | 流行度 | 平台支持 | |
|---|---|---|---|---|---|
| drift | 5月10日 👍🏻 | 1041 👍🏻 | 140 👍🏻 | 99% 👍🏻 | 全平台 👍🏻 | 
| floor | 4月25日 | 674 | 110 | 98% | Android/iOS/Mac | 
从pub上的数据来看,流行度方面,2者相差不大,drift稍微领先一点;不过点赞和评分方面,drift占优。
- 
Github对比:


数据收集日期:5月26日
| 最后提交日期 | 提交数 | Star | Issues | |
|---|---|---|---|---|
| drift | 5月25日 👍🏻 | 3054 👍🏻 | 2000+ 👍🏻 | 118 👍🏻 | 
| floor | 4月25日 | 256 | 824 | 102 | 
5月期间,Flutter发布了3.10的新版本,drift紧跟Flutter3.10适配,floor一个月没有人提交代码
在Github上,drift优势比floor大,活跃度也高,出现问题反馈比较及时。
- 
文档方面对比
drift文档地址:drift.simonbinder.eu/

floor文档地址:pinchbv.github.io/floor/

两者都提供英文文档,也提供文档搜索功能,区别不大
- 
设计方面
两者都是基于sqlite3和build_runner来开发的,不过drift支持更多的平台,也支持加密数据库
- 
drift数据库生成原理:

- 
floor数据库生成原理:

| table | model | dao | migration | |
|---|---|---|---|---|
| drift | 1.支持从sql生成 2. 支持从dart table类生成 | 1.支持从sql生成 2.  支持从dart table类生成 3.  支持使用自定义的model 类 | 1. 支持从sql生成dao 2.支持从dart dao 运行时生成sql语句(开发者不写SQL) > 直接运行sql,不用dao | 1. sql方式 2dart table类生成方式 | 
| floor | 支持从dart model 类生成 | NO |       支持从在dao中写sql生成CURD操作> 可以直接运行sql,不用dao | sql方式 | 
总结来说:
- 
drift支持sql和dart class 混合生成table、model、dao等代码;生成的model会生成比较方法,方便比较;无论哪种方式必须要有table 
- 
floor仅支持model中生成table、dao的具体查询必须要编写sql 
- 
2者都支持直接运行sql 
- 
代码示例:
drift表和 dao 定义
///drift表定义
class Todos extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 6, max: 32)();
  TextColumn get content => text().named('body')();
  IntColumn get category => integer().nullable()();
}
///drift dao定义
Future<List<Todo>> get allTodoEntries => select(todos).get();
Future<List<Todo>> limitTodos(int limit, {int offset}) {
  return (select(todos)..limit(limit, offset: offset)).get();
}
Future<List<Todo>> sortEntriesAlphabetically() {
  return (select(todos)..orderBy([(t) => OrderingTerm(expression: t.title)])).get();
}
Stream<Todo> entryById(int id) {
  return (select(todos)..where((t) => t.id.equals(id))).watchSingle();
}
floor表和 dao 定义
///floor表定义
@Entity(tableName: 'person')
class Person {
  @PrimaryKey(autoGenerate: true)
  final int id;
  @ColumnInfo(name: 'custom_name')
  final String name;
  Person(this.id, this.name);
}
///floor dao定义
@dao
abstract class PersonDao {
  @Query('SELECT * FROM Person')
  Future<List<Person>> findAllPeople();
  @Query('SELECT * FROM Person WHERE id = :id')
  Stream<Person?> findPersonById(int id);
  @insert
  Future<void> insertPerson(Person person);
}
- 
优缺点:
- 
drift相对比floor的优势:
- NoSQL
- drift支持开箱即用的在非UI Isolate中进行数据库操作
- 支持多表关联查询:Drift支持NoSQL多表关联查询,可以更方便地处理复杂的数据结构。
- 支持自定义类型:Drift支持自定义类型,可以更好地处理复杂的数据类型。而Floor只支持基本数据类型(实验性中支持自定义类型)。
Drift支持多种开箱即用的列类型。您可以使用类型转换器type converters将自定义类存储在列中。
| Dart type | Column | Corresponding SQLite type | 
|---|---|---|
| int | integer() | INTEGER | 
| BigInt | int64() | INTEGER (useful for large values on the web) | 
| double | real() | REAL | 
| boolean | boolean() | INTEGER, which a CHECK to only allow 0 or 1 | 
| String | text() | TEXT | 
| DateTime | dateTime() | INTEGER (default) or TEXT depending on options | 
| Uint8List | blob() | BLOB | 
| Enum | intEnum() | INTEGER (more information available here). | 
| Enum | textEnum() | TEXT (more information available here). | 
- 
目前发现的坑(缺点):
drift:
- 其生成的model => 写入数据库的map 是根据model中的构造方法来生成的,在使用自定义model的时候,如果字段不在构造方法中,会不生成该字段的解析
floor:
- model生成table的时候不能使用minix
- dao部分sql生成不了
- 父类和子类如果存在同名属性,会在table中生成2条同名column
- 
floor切换drift方案:
- 
table层
- 
方法一:支持把现有数据库DDL拿过来使用 - 优点:简单,快速
- 缺点:如果使用自定义model,需要修改生成的代码
 
- 
方式二:编写Table类 - 优点:数据结构相对方式一比较清晰;无需修改生成的代码
- 缺点:需要一定的人力成本编写代码
 
- 
model层
可以考虑使用现有Model,drift支持该特性 Custom row classes (simonbinder.eu)
- 
dao层
- 
方式一:使用现有代码的SQL - 优点:较为简单
- 缺点:还是SQL
 
- 
方式二:根据现有代码转换成NoSQL - 优点:NoSQL,从代码角度保证SQL不错误
- 缺点:人力成本
 
- 
migration方面
- 
方式一:使用现有代码的SQL - 优点:快速
- 缺点:还是SQL
 
- 
方式二:根据现有代码转换成NoSQL - 优点:代码清晰明了
- 缺点:人力成本
 
转载自:https://juejin.cn/post/7247045913980665911




