Flutter 5 大本地数据库解决方案

news2025/1/21 0:56:18

Flutter 5 大本地数据库解决方案

alt

原文 https://levelup.gitconnected.com/top-5-local-database-solutions-for-flutter-development-6351cd494070

前言

这里列出了最流行的数据库解决方案以及代码示例。

alt

选择正确的数据管理系统对于提高效率和可 extension 性以及影响可用性和用户体验至关重要。尽管 flutter 仍然处于早期阶段,但是有很多数据管理解决方案可供选择,其中一些已经可以投入生产。我将概述用于在本地维护数据的最常见的数据库管理系统。

正文

Sqflite

Sqflite 是一个著名的 SQLite flutter 插件。这是一个具有良好交易和批量支持的关系数据库。当数据库打开时,它会自动管理版本控制。它还包括用于常见 CRUD 操作的帮助器。后台线程处理所有数据库操作。它与 ACID 兼容,因此几乎支持所有 SQL 标准。如果您喜欢将自己的 SQL 查询编写为字符串,那么这个简单的插件将满足您的数据管理需求。

// open the database
Database database = await openDatabase(path, version: 1,
    onCreate: (Database db, int version) async {
  // When creating the db, create the table
  await db.execute(
      'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)');
});

// Insert some records in a transaction
await database.transaction((txn) async {
  int id1 = await txn.rawInsert(
      'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)');
  print('inserted1: $id1');
  int id2 = await txn.rawInsert(
      'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)',
      ['another name'123456783.1416]);
  print('inserted2: $id2');
});

// Update some record
int count = await database.rawUpdate(
    'UPDATE Test SET name = ?, value = ? WHERE name = ?',
    ['updated name''9876''some name']);
print('updated: $count');

// Get the records
List<Map> list = await database.rawQuery('SELECT * FROM Test');
List<Map> expectedList = [
  {'name''updated name''id'1'value'9876'num'456.789},
  {'name''another name''id'2'value'12345678'num'3.1416}
];

正如您从示例中看到的,我发现阅读这段代码并不容易。随着应用程序的增长,维护此代码将变得非常繁琐。因为 sqflite 是一个基本的数据库管理系统(DBMS)插件,所以我相信您应该构建自己的结构并将其包装在 sqflite 周围,就像大多数用于 flutter 的关系数据库管理系统包一样。

SQLite 通常是一个自包含的、无服务器的、轻量级的解决方案。它的性能是有争议的,但它可以让你的工作与一个耀眼的快速内存数据库。基础软件包包括移动平台支持。没有网络支持,但 sqflite_common_ffi 可以用来支持桌面平台。

floor

Floor 是一个非常有用的 SQLite 抽象,它包含一个对象映射器。它依赖于 sqflite,并在此基础上增加了类型安全等特性。它支持 sqflite 支持的所有内容,包括内存数据库。

虽然它充当 sqflite 的包装器,但它引入了更高级的概念,如 DAO 和实体。实体可以用来将内存中的对象映射到数据记录,而 DAO 允许您访问和操作数据。清楚地分隔实体、 DAO 和数据库总是一个好主意。您还可以为您的 DAO 编写好的测试,并确保您的查询通过这种方式得到验证。

@entity
class Person {
  @primaryKey
  final int id;

  final String name;

  Person(this.id, this.name);
}

前面的代码示例演示如何创建实体。地板是指导创建适当的数据库表使用注释。这是一种非常用户友好的设计数据库的方法。让我们来看看如何构建 DAO。

@dao
abstract class PersonDao {
  @Query('SELECT * FROM Person')
  Future<List<Person>> findAllPersons();

  @Query('SELECT * FROM Person WHERE id = :id')
  Stream<Person?> findPersonById(int id);

  @insert
  Future<void> insertPerson(Person person);
}

您所要做的就是提供一个具有适当注释的抽象类。遗憾的是,没有查询 API,因此仍然必须以字符串形式提供 SQL 查询。这种方法对我来说特别没有吸引力,因为这些查询没有可用的语法检查。您仍然可以测试和验证这些查询。

final personDao = database.personDao;
final person = Person(1'Frank');

await personDao.insertPerson(person);
final result = await personDao.findPersonById(1);

地板是生成必要的代码在一个建设者的帮助下。因此,所有的 DAO 都存储在数据库中。要插入一个人,您可以调用 database. person. insert tPerson (person)。老实说,我不认为通过数据库对象访问所有 DAO 是一个好主意。然而,这种丑陋可以通过使用依赖注入(DI) container 来避免。

总的来说,地板是一个有前途的平方弗莱特包装与许多有用的功能。有关详细信息,请参阅他们的文档。它通过示例和图表清楚地展示了所有特性。

Drift (Moor)

Moor 无疑是功能最丰富的 Flutter 关系数据库解决方案。它也是 sqflite 的包装器,但是它提供了更强大的功能,并且包含一个查询 API。尽管 Web 支持是实验性的,但它支持所有潜在的平台。此外,它还为事务、模式迁移、复杂的筛选器和表达式以及批处理提供了极好的支持。

它为 DAO 和实体(如 floor)提供了类似的支持,但是它是以一种高度模块化的方式进行的,允许您轻松地将它与 DI container 绑定结合起来。此解决方案的另一个优秀特性是内置的线程支持,它允许您在不需要额外工作的情况下跨隔离区运行数据库代码。最后,值得注意的是,它包含一个用于 SQL 查询的集成 IDE。多酷啊!

让我们看一些代码示例,以便您可以将其与 floor 进行比较。下面是一个如何定义表的示例。

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()();
}

我们不使用注释,而是 extension Table 类,并为该列的数据类型使用特定的列类型。在这里,我们可以为单独的列配置各种属性,比如空性、外键和约束。说到桌子的定义,我必须承认我喜欢地板的方式。它只是对我来说更具可读性,并且注释的使用是一个绝妙的概念。

这就是 DAO 的定义方式。

@DriftAccessor(tables: [Todos])
class TodosDao extends DatabaseAccessor<MyDatabasewith _$TodosDaoMixin {
  // this constructor is required so that the main database can create an instance
  // of this object.
  TodosDao(MyDatabase db) : super(db);

  Stream<List<TodoEntry>> todosInCategory(Category category) {
    if (category == null) {
      return (select(todos)..where((t) => isNull(t.category))).watch();
    } else {
      return (select(todos)..where((t) => t.category.equals(category.id)))
          .watch();
    }
  }
}

毫无疑问,您首先注意到的是查询 API,而不是基于文本的 sql 查询。就个人而言,我喜欢查询 API,因为随着项目的 extension ,您会发现一些过滤器或数据访问方法可能会被简化。您可以在不牺牲查询可读性的情况下减少代码复制。我明白,通过 SQLite 语法学习另一种 API 可能不是最舒服的选择,但它绝对是值得的。我很欣赏这样的想法,即完整的数据库逻辑可以用 Dart 编写,并且在编译过程中可以检测到可能的错误。

当我需要使用关系型本地数据库时,漂移是我的第一选择。它只是提供了一种更有效的开发和伸缩方式。因为该插件使用代码生成,所以我相信实体和 DAO 声明可能更加用户友好。该项目仍在积极开发中,每个新版本都比前一个版本有所改进。

hive

Hive 是一个非常强大和有前途的 NoSQL 数据库。它与所有平台兼容,包括网络。我没有第一手的知识,但是快速的搜索显示读写速度的基准是非常令人印象深刻的。它有很强的内置加密。将其视为一个映射,其中对象以键-值对的形式存储。

因为它是一个 NoSQL 数据库,术语“ table”被替换为术语“ box”(kind of)。因此,您的数据被组织在这些框中。因为 NoSQL 具有很强的适应性,所以您可以为每个值定义任何类型的结构。因此,框的存在并不意味着存在一致的数据模型。如果您的应用程序需要为相同类型的实体提供灵活的数据列,那么这可能是一个重要的好处。

在使用框之前,必须首先打开它,以便将数据从本地存储加载到内存中以便进行即时访问。因此,您可以在不使用“ wait”的情况下进行查询,并且在 widget 的构建方法中使用它将非常简单。如果你不需要立即访问,你可以随时使用懒箱。

var box = Hive.box('products');

box.put('name''foo');

var name = box.get('name');

print('Product Name: $name');

您可以看到如何使用上面的 Hive 创建一个盒子。这不难理解。Hive 为所有基本类型提供了基本支持,但大多数情况下,您希望存储的是实体或实体的子集。为此,必须首先创建 TypeAdapter。这里有一个例子:

@HiveType(typeId: 0)
class Product extends HiveObject {

  @HiveField(0)
  String name;

  @HiveField(1)
  int price;

  @HiveField(2)
  String color;
}

将 HiveObjects 视为实体。不过,在这种情况下,您可以 extension Product 并将其存储在同一个框中。下面是如何使用 Product 类的示例。

var box = await Hive.openBox('products');

var product = Product()
  ..name = 'Foo'
  ..price = 10
  ..color = 'orange';
box.add(product);

print(box.getAt(0)); // Foo - 10 - orange

product.price = 12;
product.save();

print(box.getAt(0)) // Foo - 12 - orange

在我看来,蜂巢是小规模和灵活应用程序的理想选择。它易于学习并适应变化。我很高兴能把它用在一个副业上。

sembast

Sembast 是另一个用于 Flutter (和 Dart )应用程序的 NoSQL 数据库,它支持所有可能的平台,包括 web (通过 Sembast web 包)。Sembast 由于其有前途的功能而在这个名单上,但我不相信它还在那里。它以类似于 Hive 的方式管理数据库,但有一些不同之处。我没有看到任何对实体的支持,我认为这在数据模式可读性方面是有益的。您仍然可以使用自己的类型,但它们必须是正确编码/解码的 JSON。

// File path to a file in the current directory
String dbPath = 'sample.db';
DatabaseFactory dbFactory = databaseFactoryIo;

// We use the database factory to open the database
Database db = await dbFactory.openDatabase(dbPath);

若要使用数据库,必须使用。分贝 extension 。此文件将用于所有数据库操作,并将根据需要进行更新。如果你不想使用这个选项,你仍然可以通过 sqflite 使用 Sembast。

// dynamically typed store
var store = StoreRef.main();
// Easy to put/get simple values or map
// A key can be of type int or String and the value can be anything as long as it can
// be properly JSON encoded/decoded
await store.record('title').put(db, 'Simple application');
await store.record('version').put(db, 10);
await store.record('settings').put(db, {'offline'true});

// read values
var title = await store.record('title').get(db) as String;
var version = await store.record('version').get(db) as int;
var settings = await store.record('settings').get(db) as Map;

// ...and delete
await store.record('version').delete(db);

在上面,您可以看到如何保存和读取记录。API 学起来很简单,但我更喜欢 Hive 语法而不是 Sembast 语法,因为它省去了在读取数据时“等待”的需要。但是,你仍然可以探索森巴斯特。值得注意的是,Sembast 支持“触发器”和“数据加密”这两个有用的特性可以帮助提高数据的安全性和一致性。

shared_preferences

如果您的应用程序不是数据关键型的,那么您就不需要花费大量时间学习额外的库。共享首选项使用特定于平台的存储 API 来存储和读取键值对。因为数据可以异步地保存到磁盘上,所以这个插件不应该用来存储关键数据。

_incrementCounter() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  int counter = (prefs.getInt('counter') ?? 0) + 1;
  print('Pressed $counter times.');
  await prefs.setInt('counter', counter);
}

正如您所看到的,使用该插件是简单和直接的。

关系数据库或 NoSQL

我觉得有义务解释关系数据库管理系统和 NoSQL 解决方案之间的区别。它们都有优点和缺点,但这不是重点。因为我们不能说一个比另一个好。归根结底就是你的需要。

「关系数据库 Relational DBMS:」

  • 数据一致性
  • 数据模式不太可能发生显著变化
  • 存储实际数据和数值数据

「NoSQL:」

  • 数量庞大,数据混乱
  • 灵活的模式定义,实时数据,更容易伸缩
  • 没有连接,查询速度更快,但数据复制更多

这些是两个数据库系统的关键特性。当涉及到使用本地数据库进行开发时,您应该彻底理解应用程序的数据需求。

如果您正在开发同时具有数字产品和实体产品的商店应用程序,那么这些产品可能具有多种特性。即使是同一类别的产品也可以有不同的特点。在这种情况下,您需要一个 NoSQL 数据库,否则最终会得到一大堆可为空的列。

考虑另一个示例应用程序,比如加密货币投资组合应用程序。当然,您的应用程序将依赖于第三方 API。这些 API 经常更改。您可以使用 NoSQL 数据库,而不是每次都更改模式,这比使用关系型 DBMS 更容易适应更改。我相信你明白这一点,但是你可以关于这一主题的文章,以帮助你为未来的项目做出更好的决策。

Conclusion

结论

我试图简化用于 flutter 开发的最流行的本地数据库解决方案的基本原理。这些都是非常棒的软件包,背后都有非常聪明的头脑。试着通过给他们星级或者为他们的知识库做贡献来帮助他们。我希望这篇文章对你决定下一个数据库解决方案有帮助。

最后一个想法。我很了解「幻界」和「伊萨」的数据库我知道他们正在崛起。这里没有列出它们,因为它们最近才发布了 alpha 版本。

谢谢你宝贵的时间。

结束语

如果本文对你有帮助,请转发让更多的朋友阅读。

也许这个操作只要你 3 秒钟,对我来说是一个激励,感谢。

祝你有一个美好的一天~


© 猫哥

  • 微信 ducafecat

  • https://wiki.ducafecat.tech

  • https://video.ducafecat.tech

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/40827.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3DConvCaps:3DUNet与卷积胶囊编码器用于医学图像分割

摘要 卷积神经网络需要大量的训练数据&#xff0c;无法处理物体的姿态和变形。此外其中的池化层也倾向于丢弃位置等重要的信息。CNN对旋转和仿射变换非常敏感。 胶囊网络是最近出现的一种新型体系结构&#xff0c;其通过动态路由和卷积步长代替池化层&#xff0c;在部分整体表…

steam搬砖项目的核心内容解答

大家好&#xff0c;我是阿阳 如果你有个几千块钱积蓄&#xff0c;想做点小生意&#xff0c;又不知道做啥&#xff0c;那我建议你来做steam搬砖&#xff0c;steam搬砖是什么呢&#xff1f;steam搬砖怎么赚钱的呢&#xff1f;你听我一步步跟你说来 steam搬砖是什么呢&#xff1f…

详解GMM高斯混合模型EM模型

一般讲到GMM就会讲到EM。 我不过多的介绍EM算法。这里只是举一些例子来看看真实的GMM怎么用EM算的。 一、GMM的作用 记住GMM的作用&#xff0c;就是聚类&#xff01; 二、GMM有hard和soft两种 hard-GMM和soft-GMM是为了对标k-means和soft k-means。在中文互联网上搜索到的GM…

【SVM分类】基于matlab哈里斯鹰算法优化支持向量机SVM分类【含Matlab源码 2243期】

⛄一、哈里斯鹰算法简介 HHO算法用数学公式来模拟现实中哈里斯鹰在不同机制下捕捉猎物的策略.在HHO中&#xff0c;哈里斯鹰是候选解&#xff0c;猎物随迭代逼近最优解.HHO算法包括两个阶段&#xff1a;全局探索阶段、局部开采阶段。 1 全局探索阶段 在这一阶段中&#xff0c;哈…

springboot thymeleaf使用

导入依赖 <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.0.11.RELEASE</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <a…

springboot集成swagger并更换主题

前言 swagger对于web一个开发人员&#xff0c;可以说是非常熟悉的了&#xff0c;之前都是用的公司搭好的框架拿来就用&#xff0c;自己也没有研究过&#xff0c;最近想搞一个自己拿来练手的基础框架&#xff0c;因此来记录一下springboot集成swagger的过程和注意事项。 swagg…

云南白药正在度过“中年危机”

​文丨熔财经 作者|kinki 今年&#xff0c;正是云南白药创制的120周年&#xff0c;虽然是一个百年老字号品牌&#xff0c;但在过去的数年间&#xff0c;云南白药在新品研制、跨界发展乃至品牌推广上都做了不少新尝试。今年&#xff0c;云南白药更提出了“141”战略&#xff0…

备战 2023 春招,P7大咖位手打 26 大后端面试专题神技,1500+题解析助力offer

年过后&#xff0c;不少人已经蓄势待发&#xff0c;信心满满地准备投递简历&#xff0c;到处面试&#xff0c;在不同的 Offer 之中择优而栖。 与此同时&#xff0c;也有人会悔恨自己这半年进步不大&#xff0c;每天噼里啪啦敲代码&#xff0c;但面对那些不能再熟悉的 Java 面试…

分布式解决方案 Percolator--详解

Percolator简介 Google在2012年将Percolator的架构设计作为论文发表&#xff0c;其目的是构建于BigTalbe的基础上&#xff0c;主要用于网页搜索索引等服务。由于BigTable只支持单行级别的事务&#xff0c;不支持多行事务等更复杂的事务&#xff0c;因此Percolator的诞生就是为了…

数据增强:Simple Questions Generate Named Entity Recognition Datasets

数据增强的方式一般是无标注数据集的情形的一种解决方式&#xff0c;今天的讲座报告中对这问题做了梳理。11.27学术报告文章&#xff0c;应该是韩旭的报告。 文章目录问题背景一、论文核心二、文章内容三、experiments总结问题背景 还是在于方法的创新&#xff0c;虽然是数据增…

Centos7下安装Oracle11g

1. 下载安装包 由于Oracle官网上无法下载Oracle数据库之前的版本&#xff0c;可以在 Oracle Software Delivery Cloud 里搜索oracle database 11g 或者百度网盘下载链接&#xff1a;https://pan.baidu.com/s/1r57xI5fSVba_Q3biCj06yg 提取码&#xff1a;xk30 2. 创建运行ora…

【BSC】使用Python玩转PancakeSwap(入门篇)

需求 最近我们需要在BSC上实现代币的自动化兑换&#xff0c;比如自动把BNB兑换成USDT&#xff0c;自动把USDT兑换成CAKE等其它代币&#xff0c;同时也要监视价格&#xff0c;在价格合适的时候再兑换代币。而PancakeSwap正是BSC上最大的去中心化平台&#xff0c;我们已经学会了…

潜匿的怪物,你的供应链真的安全吗?

网络钓鱼、DNS欺骗      勒索软件、MITM攻击      在这个网络环境      风声鹤唳的时代      这些网络攻击类型      你一定不会感到陌生      无孔不入,这个词用来形容网络攻击毫不为过。世上没有绝对锋利的矛,同样也没有坚不可摧的盾,即使您养成了安…

如何编写列名中带有空格的SQL查询

在这篇文章中&#xff0c;我们将学习如何写出列名中带有空格的SQL查询。空格在数据库对象的名称和表的列名的命名规则中受到限制。如果你想在对象名或列名中加入空格&#xff0c;查询和应用代码必须以不同的方式编写。在编写动态SQL查询时&#xff0c;你必须小心和精确。本文解…

【JavaWeb】Servlet系列 --- Tomcat安装及配置和常见的问题(2022最新详解、图文教程)

Tomcat的配置安装1. 关于WEB服务器软件2. 配置Tomcat的服务器第一步&#xff1a;配置Java的运行环境第二步&#xff1a;Tomcat的安装第三步&#xff1a;启动Tomcat3. 问题一&#xff1a;解决Tomcat服务器在DOS命令窗口中的乱码问题&#xff08;控制台乱码&#xff09;4. 测试To…

linux 用户不在sudoers文件中,此事将被报告

出现如下提示 gaokaoli 出现不在 sudoers 文件中。此事将被报告 一般是该用户 权限不够 既然知道权限不够可以添加到root用户组&#xff0c;获取权限即可 通过命令行添加到权限&#xff0c;发现还是不行 sudo usermod -g root gaokaoli 那就直接在配置文件中修改 通过执行…

word设置页码从非第一页开始

设置过程 参考&#xff1a;https://zhuanlan.zhihu.com/p/84998841 显示出分隔符和分页符 方法一&#xff1a; 在文档中直接按【CtrlShift8】组合键&#xff0c;即可显示出分节符。. 方法二&#xff1a; 点击【开始】-【段落】-【显示/隐藏编辑标记】按钮&#xff0c;也可显…

如何安装Jmeter监控服务器资源插件(JMeterPlugins + ServerAgent 方法一)?

一、下载插件 ServerAgent-2.2.3.zip 下载 JMeterPlugins-Extras-1.4.0.zip下载 JMeterPlugins-Standard-1.4.0.zip下载 &#xff08;或者可以到网站下载插件&#xff1a;JMeterPlugins-Standard和JMeterPlugins-Extras 下载地址&#xff1a;https://jmeter-plugins.org/down…

计算机图形学(三) -- 3D 变换

文章目录3D 变换缩放(Scale)平移(Translation)旋转(Rotation)3D 旋转(3D Rotation)什么是欧拉角罗德里格斯旋转公式(Rodrigues Rotation Formula)Viewing transformation什么是 View / Camera Transformation相机标准位置(约定俗成)怎样将一个相机从一个任意的摆放&#xff0c;…

clickhouse单节点以及集群的安装

安装 因为clickHouse很消耗cpu资源&#xff0c;所以需要修改&#xff1a;用户可打开的文件数量和最大进程数&#xff1a; vim /etc/security/limits.conf * soft nofile 65536 * hard nofile 65536 * soft nproc 131072 * hard nproc 131072//第一列代表用户用户组&#x…