flutter数据库

flutter 数据库

This article was originally published here on the Codemagic blog

本文最初发布在 Codemagic博客

There are a lot of options out there today when it comes to databases in your application. They typically fit into these three categories:

对于应用程序中的数据库,今天有很多选择。 它们通常适合以下三类:

  • Relational — these are the databases in the traditional sense. They don’t just store data but also the relationships between the data. SQLite is an example of a relational database.

    关系式 -这些是传统意义上的数据库。 它们不仅存储数据,还存储数据之间的关系 。 SQLite是关系数据库的一个示例。

  • NoSQL — these databases store data as documents. A schema is not enforced as is the case with a relational database. They are lightning-quick and handle huge unstructured pieces of data very well. MongoDB is an example of a NoSQL database.

    NoSQL-这些数据库将数据存储为文档 。 与关系数据库不同,没有强制执行架构。 它们闪电般迅捷 ,可以很好地处理大量非结构化数据。 MongoDB是NoSQL数据库的示例。

  • Individually tailored data storage — while this option is not technically a database, you don’t have to use the above solutions. You can store your data in a JSON file and handle the serialisation and deserialisation yourself. This would be incredibly fast but would open you up to some weird bugs if you weren’t a programming genius. 🤓

    量身定制的数据存储 -尽管从技术上讲该选项不是数据库,但您不必使用上述解决方案。 您可以将数据存储在JSON文件中,并亲自处理序列化和反序列化。 这将是非常快的,但是如果您不是编程天才,则会使您遇到一些奇怪的错误。 🤓

By the end of this article, you will know:

到本文结尾,您将知道:

  • The basics of how each database works. 📰
    每个数据库的工作原理。 📰
  • How to get set up with each database. ⚙
    如何建立每个数据库。 ⚙
  • What a good use case would be for each database. 📳
    每个数据库都有一个很好的用例。 📳

In this article, we’ll divide our database types according to the three categories mentioned above.

在本文中,我们将根据上述三个类别来划分数据库类型。

关系型 (Relational)

Relational databases have been around for a very long time (since 1970, according to a quick Google search). Let’s look at some of the options you have on Flutter for relational databases today.

关系数据库已经存在很长时间了(根据Google的快速搜索,自1970年以来)。 让我们看看您在Flutter上为关系数据库所拥有的一些选项。

SQflite (SQflite)

SQflite is an implementation of SQLite for Flutter. It affords you complete control over your database, queries, relationships, everything you could wish for.

SQflite是SQLite for Flutter的实现。 它使您可以完全控制数据库,查询,关系以及所有想要的东西。

Interacting with a SQLite database in Flutter looks like this (from the docs):

在Flutter中与SQLite数据库进行交互看起来像这样( 来自docs ):

// Get a location using getDatabasesPath  
var databasesPath = await getDatabasesPath(); 
String path = join(databasesPath, 'demo.db');  
// Delete the database  
await deleteDatabase(path);    
// 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)');
  });

Inserting data follows the same age-old SQLite tenants  

// 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', 12345678, 3.1416]);   print('inserted2: $id2');
  });

And querying happens like this:

查询发生如下:

// Get the records
  List<Map> list = await database.rawQuery('SELECT * FROM Test');

优点👍 (Pros 👍)

  • Total control over the database.
    完全控制数据库。
  • A very efficient SQLite database for your app (given that you have pre-existing SQLite knowledge).
    适用于您应用的高效SQLite数据库(前提是您已具备SQLite知识)。
  • Easily read by third party apps that can open SQLite databases (so you can open the database on your computer and see what the data looks like).
    可以打开SQLite数据库的第三方应用程序可以轻松读取(因此您可以在计算机上打开数据库,查看数据是什么样的)。

缺点👎 (Cons 👎)

  • Writing out all your queries by hand can take a lot of time.
    手工写出所有查询会花费很多时间。
  • Returned data from the database isn’t strongly typed from the start.
    从数据库开始返回的数据从一开始就不是强类型的。
  • It is potentially difficult to handle migrations on the device (when the schema changes between version updates for instance).
    处理设备上的迁移可能很困难(例如,当模式在版本更新之间更改时)。
  • It has no support for web.
    它不支持网络。

用例 (Use case)

SQFlite is good when you need relational data but also fine-grained control over the actual queries. If you’re comfortable with writing your own queries and don’t mind writing both a lot of queries and the code to convert the results to and from your classes, this could be a good fit for you.

当您需要关系数据时,SQFlite是很好的选择,而且还可以对实际查询进行细粒度的控制。 如果您对编写自己的查询感到满意,并且不介意编写大量查询和将结果与类进行相互转换的代码,那么这可能非常适合您。

SQLite抽象 (SQLite abstractions)

Directly using SQLite to manage your application database can be quite powerful but also unwieldy. That’s why there are so many solutions that abstract some of the functionality from SQLite into more easily used functionality. These abstractions can make a SQLite database easier to use, while still retaining a lot of the benefits of SQLite.

直接使用SQLite管理您的应用程序数据库可能非常强大,但也很麻烦。 这就是为什么有这么多解决方案将SQLite的某些功能抽象为更易于使用的功能的原因。 这些抽象可以使SQLite数据库更易于使用,同时仍然保留SQLite的许多优点。

Floor and Moor are fairly popular examples of this approach. In this article we’ll look at Moor, but the approach that these two packages take in abstracting SQLite is fairly similar.

FloorMoor是这种方法相当受欢迎的示例。 在本文中,我们将探讨Moor,但是这两个软件包在抽象SQLite中所采用的方法非常相似。

泊 (Moor)

In order to use Moor, we import the Moor package from flutter pub, but we also have to import something called the moor_generator. This is used by build_runner to generate the code to use the database.

为了使用Moor,我们从flutter pub导入了Moor包,但是我们还必须导入一个称为moor_generator东西。 build_runner使用build_runner来生成使用数据库的代码。

Why do we use build_runner ? build_runner is primarily used to generate code for your Flutter projects. Before I came to Flutter, I rarely, if ever, had to use a code generation utility. The main reason for this is because most other languages that I had used up until this point (such as C#) supported reflection.

为什么我们使用 build_runnerbuild_runner 主要用于 为Flutter项目 生成代码。在来Flutter之前,我很少(如果有的话)必须使用代码生成实用程序。这样做的主要原因是因为到目前为止我用尽的其他大多数语言(例如C#)都支持反射

Simply put, this makes it possible for the framework to dynamically invoke parts of the program at runtime. It’s quite powerful, but typically it can be quite slow. It also affects linking of the produced application, as with reflection, technically every part of your application could be accessed or used.

简而言之,这使框架可以在运行时动态调用程序的各个部分。 它功能强大,但通常速度可能很慢。 它也影响 生成的应用程序的 链接 ,就像反射一样,从技术上讲,您的应用程序的每个部分都可以访问或使用。

When packages use functionality that typically were provided by reflection, they usually use build_runner to generate the necessary code ahead of time. This results in faster code execution at runtime, and also results in better ‘tree shaking’, or minimisation of the application binary at deployment time.

当程序包使用通常由反射提供的功能时,它们通常使用 build_runner 提前生成必要的代码。 这样可以在运行时更快地执行代码,还可以在部署时更好地“摇树”或最小化应用程序二进制文件。

A look into the Getting Started documentation helps us understand the way a database is created.

查看“入门”文档可帮助我们了解创建数据库的方式。

import 'package:moor/moor.dart';
// assuming that your file is called filename.dart. This will give an error at first,
// but it's needed for moor to know about the generated codepart 'filename.g.dart';
// this will generate a table called "todos" for us. The rows of that table will
// be represented by a class called "Todo".
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()();
}
// This will make moor generate a class called "Category" to represent a row in this table.
// By default, "Categorie" would have been used because it strips away the trailing "s"
// in the table name.
@DataClassName("Category")
class Categories extends Table {
  IntColumn get id => integer().autoIncrement()();
 TextColumn get description => text()();
}
// this annotation tells moor to prepare a database class that uses both tables
// we just defined. We'll see how to use that database class in a moment.
@UseMoor(tables: [Todos, Categories])
class MyDatabase { }

Moor programatically creates the schema for your tables depending on how you define their contents. In the beginning of this code example, we can see the part statement. When we run the build_runner command, moor generates the schema based on what we have defined in this file. You can also drop back to raw SQL at any time if you need to run a specific query or if you want more fine-grained control.

Moor通过编程方式为您的表创建架构,具体取决于您定义表内容的方式。 在此代码示例的开头,我们可以看到part语句。 当我们运行build_runner命令时, moor根据我们在此文件中定义的内容生成架构。 如果需要运行特定查询或需要更细粒度的控制,则还可以随时返回原始SQL。

优点👍 (Pros 👍)

  • Strongly typed results!

    强类型结果!

  • Based on SQLite.
    基于SQLite。

  • You don’t have to manually construct every query by hand.
    您不必手动构造每个查询。

  • A lot of the heavy lifting is handled by code generation.
    许多繁重的工作由代码生​​成处理。

  • SQLite database can be navigated with a wide range of tools available today to check data during development.
    可以使用当今可用的各种工具来浏览SQLite数据库,以在开发期间检查数据。

缺点👎 (Cons 👎)

  • It can be cumbersome to handle schema updates on the local device.
    在本地设备上处理架构更新可能很麻烦。
  • Web support is still in preview.
    Web支持仍在预览中。
  • It has platform-specific dependencies (not written in pure Dart).
    它具有特定于平台的依赖性(不是用纯Dart编写的)。

用例 (Use case)

If you still need relational data but want to write as little SQL as possible (if you are used to Entity Framework, for instance), this could be a good fit for you.

如果您仍然需要关系数据,但想编写SQL越少越好(例如,如果您习惯使用Entity Framework),那么这可能是您的理想选择。

NoSQL (NoSQL)

There are quite a few options when it comes to NoSQL databases for Flutter as well. We have the heavy hitters that have been around for a long time like Firebase, as well as the newer solutions like Hive. There are many differences between Hive and Firebase but perhaps the main difference is that one can sync to an online store (Firebase), whereas the other is more adequately suited for storing locally on the device (Hive).

Flutter的NoSQL数据库也有很多选择。 我们拥有像Firebase这样已经存在很长时间的重量级选手,以及像Hive这样的较新解决方案。 Hive和Firebase之间有许多区别,但也许主要区别在于,一个可以同步到在线商店(Firebase),而另一个更适合于在设备上本地存储(Hive)。

Firebase —在线NoSQL存储 (Firebase — online NoSQL storage)

Firebase is a traditional document storage database. You store data in collections that are like tables in a traditional database. These collections store documents. Documents store data types, like string, int, etc. They can also store a link to another document, so even though Firebase isn't strictly relational you can still create relationships between your data.

Firebase是传统的文档存储数据库。 您将数据存储在类似于传统数据库中表的集合中。 这些集合存储文档 。 文档存储数据类型,例如stringint等。它们还可以存储指向另一个文档的链接,因此,即使Firebase不是严格关系的,您仍然可以在数据之间创建关系。

The setup for Firebase is quite involved compared to other on-device options, like Moor or Hive, but you get synchronisation of data between clients and the server. This means that if you have multiple clients with an app and they are all interacting with the same data, then this data can be kept in sync between these clients. Also, this setup is covered quite well in a Google Codelab here. The only downside of this approach is that you don’t get strongly typed data in the same way as you do with Moor or Hive. You have to handle this yourself.

与其他设备上选项(例如Moor或Hive)相比,Firebase的设置相当复杂,但是您可以在客户端和服务器之间实现数据同步 。 这意味着,如果您有一个应用程序有多个客户端,并且它们都与同一数据进行交互,则可以使这些客户端之间的数据保持同步。 另外, 此处的Google Codelab很好地介绍了此设置。 这种方法的唯一缺点是,您不会像使用Moor或Hive那样获得强类型数据。 您必须自己处理。

优点👍 (Pros 👍)

  • Synchronises with Firebase online in a near real-time fashion.
    以近乎实时的方式与Firebase在线同步。
  • Great tooling support.
    强大的工具支持。
  • Easy to browse data online via the Firebase Console.
    通过Firebase控制台轻松在线浏览数据。

缺点👎 (Cons 👎)

  • Firebase setup can be complicated if you don’t already have it added to your app.
    如果您尚未将Firebase安装添加到应用程序中,则可能会很复杂。
  • As the database is online, you need to be mindful of a lot more than a strictly on-device database (like access permissions, for instance).
    由于数据库在线,因此您需要注意的不仅仅是严格的设备数据库(例如,访问权限)。
  • Firebase support for Flutter isn’t in a production ready state just yet.
    对Flutter的Firebase支持尚未处于生产就绪状态。

用例 (Use Case)

If your data is to be spread between many devices and you want (relatively) painless synchronisation between these devices, this could be a good solution for you.

如果您的数据要分散在许多设备之间,并且您想要(相对)在这些设备之间进行轻松的同步,那么这可能是一个很好的解决方案。

Hive-离线NoSQL存储 (Hive — offline NoSQL storage)

Hive is an extremely fast NoSQL storage option for Flutter developers. Its biggest selling point is that it is completely native to Dart. This means that anywhere Dart goes, Hive can go, as it doesn’t require any device-specific implementations.

对于Flutter开发人员来说,Hive是一种非常快速的 NoSQL存储选项。 它最大的卖点是它完全是Dart 原生的 。 这意味着Dart可以进行任何操作 ,Hive可以进行,因为它不需要任何特定于设备的实现

Hive lets you store data as a HiveObject, which allows for some relations between objects as well. It stores objects in a box, but you can generate TypeAdapters for them.

Hive允许您将数据存储为HiveObject ,这也允许对象之间存在某些关系。 它将对象存储在一个box ,但是您可以为它们生成TypeAdapter

Creating a box is fairly simple:

创建一个box很简单:

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

Reading and writing is just as easy:

读写很容易:

import 'package:hive/hive.dart';
void main() async {
 var box = await Hive.openBox('testBox');
 box.put('name', 'David');
 print('Name: ${box.get('name')}');
}

Where Hive really shines is in the ability to generate TypeAdapters (read more from the documentation). This brings strong typing to your Boxes, and lets you store your classes, and also lets you reference objects in other Boxes.

Hive真正出众的地方在于能够生成TypeAdapter (从文档中阅读更多内容 )。 这为Box提供了强大的输入功能,并允许您存储类,还可以引用其他Box中的对象。

The documentation shows how to create a box based on a class with your own definition, like below.

该文档显示了如何根据具有自己定义的类创建box ,如下所示。

import 'package:hive/hive.dart';

part 'person.g.dart';
 @HiveType()
 class Person {

 @HiveField(0) String name;
 @HiveField(1) int age;
 @HiveField(2) List<Person> friends;
}

As we can see here, this class contains a List of Person, so Hive can reference a list of objects.

正如我们在这里看到的那样,该类包含一个Person List ,因此Hive可以引用一个对象列表。

用例 (Use case)

If you are just after a simple database to store data on your device, and don’t want the synchronisation that Firebase offers and if you want something that works anywhere, Hive is for you. It’s the database I use in all my apps.

如果您只是想在一个简单的数据库中将数据存储在设备上,并且不希望Firebase提供同步功能,并且希望在任何地方都可以使用,则Hive适合您 。 这是我所有应用程序中使用的数据库。

自己做 (Making your own)

If you’re not smitten with any of the above options, you could roll your own database. You would achieve this through using a library like json_serializable, and storing the JSON files on the device for the app to access.

如果您不喜欢上面的任何选项,则可以滚动自己的数据库。 您可以通过使用json_serializable类的库并将JSON文件存储在设备上以供应用访问来实现。

In my opinion, this would be a little bit like building your own car from scratch. Of course, you can do it, and people have done it, but I’m not sure why you would. Creating a new database means creating a new library with potential bugs and so many new issues to consider and think about. If you have set out to make an app, is creating your own database solution really within the scope of doing that?

我认为,这有点像从头开始建造自己的车。 当然,您可以做到,而且人们已经做到了,但是我不确定为什么会这样做。 创建一个新数据库意味着创建一个具有潜在错误以及许多新问题要考虑和思考的新库。 如果您打算制作一个应用程序,那么创建自己的数据库解决方案真的在该范围内吗?

Existing solutions like Hive or Moor are already in use by a lot of people, all finding bugs and filing issues on GitHub. This is what gives these libraries quality. Who would find bugs on your brand-new, from scratch database? Because you’re the only person that uses it, only you would. That doesn’t sound very appealing does it? I hope not.

像Hive或Moor这样的现有解决方案已经被很多人使用,他们都在GitHub上发现错误并提交问题。 这就是赋予这些库质量的原因 。 谁会从头开始在您的全新数据库中发现错误? 因为您是唯一使用它的人,所以只有您会使用 。 听起来不是很吸引人吗? 我希望不是。

用例 (Use case)

If you completely distrust all code not written by you, or you have some weird esoteric use case, you would maybe consider making your own. I wouldn’t consider doing this in any app I would make though …

如果您完全不信任您未编写的所有代码,或者您有一些怪异而深奥的用例,则可以考虑自己制作。 我不会考虑在我会制作的任何应用程序中这样做……

这么多的选择! 我应该使用哪一个? (So many options! Which one should I use?)

There’s not an easy way to answer what database is “best” — it depends on your use case. But let me sum it up.

没有哪种简单的方法可以回答哪个数据库是“最佳”数据库,这取决于您的使用场景。 但让我总结一下。

  • If your data is relational and you want to be able to view it on your computer easily during development — and you don’t mind not having web support — you should use moor.

    如果您的数据是关系型的,并且希望在开发过程中可以轻松地在计算机上查看它-并且您不介意没有Web支持,则应该使用moor

  • If you need your data synchronized between devices and you don’t mind the fairly extended setup, you should use Firebase.

    如果您需要在设备之间同步数据并且不介意扩展设置, 则应使用Firebase

  • If you want to be up and running really quickly and want great support for the web plus anything else Dart runs on, you should use Hive.

    如果您想快速启动并运行,并且希望获得对Web的大力支持以及Dart运行的其他功能,则应该使用Hive

  • If you have crippling doubt about the security of these databases and nobody can convince you otherwise, and you have a lot of time on your hands, you could consider making your own database or object store with JSON objects. But I wouldn’t.

    如果您对这些数据库的安全性有严重的怀疑 ,并且没有人可以说服您,并且您有很多时间可用,则可以考虑使用JSON对象创建自己的数据库或对象存储。 但是我不会。

If I was making an app today, I would probably use Hive.

如果我今天要开发一个应用程序,那么我可能会使用Hive

Thanks for reading this article on databases for Flutter. I hope it has made choosing one a little easier for you!

感谢您阅读有关Flutter数据库的文章。 我希望它使您更轻松地选择一个!

Is there another Flutter topic that you would just love to know more about? Let me know in the comments! 😊

是否有其他Flutter话题,你想要有更多的了解? 在评论中让我知道! 😊

https://www.twitter.com/FlutterComm

https://www.twitter.com/FlutterComm

翻译自: https://medium.com/flutter-community/choosing-the-right-database-for-your-flutter-app-39ea07e7f6e6

flutter 数据库

转载自weixin_26638123的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272