Flutter笔记: 在Flutter应用中使用SQLite数据库

简介: Flutter笔记: 在Flutter应用中使用SQLite数据库

Flutter笔记在Flutter应用中使用SQLite数据库(基于sqflite)


1. 概述

SQLite是一种轻量级的嵌入式关系型数据库管理系统,而在Flutter中,我们可以通过使用 sqflite 模块方便地进行SQLite数据库的操作。本文将介绍如何在Flutter应用中使用 sqflite 来进行数据库操作。如果你对ORM(对象关系映射)有兴趣,可以参考以下文章:

在接下来的内容中,我们将深入了解如何使用 sqflite 在Flutter应用中创建、查询、更新和删除数据库记录,以及如何执行异步操作和处理数据库版本升级。

2. 安装和配置 sqflite

在使用 sqflite 之前,我们需要将其添加为Flutter应用的依赖项,并在代码中导入相应的模块。

2.1 添加依赖

打开你的Flutter应用的 pubspec.yaml 文件,并在 dependencies 部分添加 sqflite 依赖:

dependencies:
  sqflite: ^2.3.0

这将使用指定版本的 sqflite 库。你可以通过 pub.dev 查看最新版本。

保存 pubspec.yaml 文件后,运行以下命令来获取依赖:

flutter pub get

如果你想直接安装最新版本亦可以通过运行下面的命令:

flutter pub add sqflite

这将在 pubspec.yaml 文件中添加最新版本作为依赖,并隐式的运行一个 flutter pub get 命令。

2.2 导入模块

在你的Dart文件中,导入 sqflite 模块:

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
// 其他导入...

以上是在Flutter应用中添加和配置 sqflite 的步骤。在接下来的部分,我们将深入研究如何使用 sqflite 进行数据库操作。

3. SQL 基础知识 和 SQLite 工具

3.1 创建表

在SQL中,我们使用CREATE TABLE语句来创建新的表。以下是创建表的示例代码:

CREATE TABLE my_table(
  id INTEGER PRIMARY KEY,
  name TEXT
);

在上面的SQL语句中,我们创建了一个名为my_table的表,它有两个字段:id和name。id字段是整数类型,并作为主键,name字段是文本类型。

3.2 插入数据

在上面的SQL语句中,我们使用INSERT INTO语句来插入新的数据。以下是插入数据的示例代码:

INSERT INTO my_table(id, name) VALUES(1, 'Jack');

在上面的SQL语句中,我们向my_table表插入了一条新的数据,id字段的值为1,name字段的值为’Jack’。

3.3 查询数据

在SQL中,我们使用SELECT语句来查询数据。以下是查询所有数据的示例代码:

SELECT * FROM my_table;

在上面的SQL语句中,我们查询了my_table表的所有数据。

3.4 更新数据

在SQL中,我们使用UPDATE语句来更新数据。以下是更新数据的示例代码:

UPDATE my_table SET name = 'Bob' WHERE id = 1;

在上面的SQL语句中,我们更新了my_table表中id字段为1的数据,将name字段的值改为’Bob’。

3.5 删除数据

在SQL中,我们使用DELETE FROM语句来删除数据。以下是删除数据的示例代码:

DELETE FROM my_table WHERE id = 1;

在上面的SQL语句中,我们删除了my_table表中id字段为1的数据。

3.6 数据库工具

SQLiteSpy 工具

SQLiteSpy 是一款免费的快速且紧凑的图形用户界面(GUI)工具,用于管理 SQLite 数据库,你可以自由地下载和使用。它的设计目标是使得 SQLite 数据库的开发和维护变得更加简单和轻松。SQLiteSpy 提供了丰富的功能,包括数据库结构查看、SQL 查询编辑器、数据导入/导出等。它还支持 SQLite 的所有数据类型,包括 BLOB。

下载地址:https://download.csdn.net/download/qq_28550263/88545032

在 Windows 上调试运行 Flutter 时,数据库文件位置在 项目根目录.dart_tool\sqflite_common_ffi\databases

Android Studio

可以可以在插件市场搜索一个你喜欢的SQLite插件:

然后打开 设备文件浏览器

然后在应用下找到数据库文件。

如果使用 Floor 的话,数据库时自动创建的。假设你的应用的包名是 my_app,那么你的应用的数据库文件应该位于 /data/data/com.example.my_app/databases/ 目录下。

双击后,数据库插件将在新的标签中打开:

(此处演示的表是空的,但是可以看到表的各个字段)

4. 创建数据库

4.1 定义数据库路径

首先,我们需要定义数据库文件的路径。在 AndroidiOS 上,我们通常将数据库文件存储在设备的文件系统中。我们可以使用 path_provider 库来获取这些路径。

首先,添加 path_provider 依赖到你的 pubspec.yaml 文件:

dependencies:
  flutter:
    sdk: flutter
  sqflite: any
  path_provider: any

然后,导入path_provider和sqflite库,并定义一个函数来获取数据库路径:

import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'dart:io' as io;
import 'package:path/path.dart';
// 定义一个异步函数来获取数据库路径
Future<String> getDatabasePath(String dbName) async {
  // 获取应用的文档目录
  final directory = await getApplicationDocumentsDirectory();
  // 拼接路径
  final path = join(directory.path, dbName);
  return path;
}

作为对比,以前介绍过 Floor 库。Floor 是一个基于 SQLiteORM 框架,它在底层使用了 sqflite 库。但是,Floor 框架已经封装了数据库路径的获取和数据库的创建,所以在使用 Floor 框架时,你不需要显式地使用 path_provider 库来获取数据库路径。

当你使用 Floor 框架创建数据库时,只需要提供数据库的名称,Floor 框架会自动为你处理数据库路径的问题。例如:

final database = await $FloorAppDatabase
  .databaseBuilder('app_database.db')
  .build();

4.2 创建数据库表

有了数据库路径,我们就可以创建数据库和表了。我们可以定义一个函数来创建数据库和表:

Future<Database> createDatabase() async {
  // 获取数据库路径
  final path = await getDatabasePath('my_db.db');
  // 打开数据库
  final database = openDatabase(
    path,
    version: 1,
    // 当数据库第一次被创建时,执行创建表的操作
    onCreate: (db, version) {
      return db.execute(
        "CREATE TABLE my_table(id INTEGER PRIMARY KEY, name TEXT)",
      );
    },
  );
  return database;
}

在上述代码中,我们首先调用openDatabase函数并传入数据库路径。如果数据库文件不存在,openDatabase函数会创建一个新的数据库文件。然后,我们定义了一个onCreate回调函数,当数据库第一次被创建时,这个函数会被调用。在这个函数中,我们执行了一个SQL语句来创建一个新的表my_table。

5. 插入数据

5.1 创建数据模型

在插入数据之前,我们通常会创建一个数据模型来表示我们的数据。以下是一个简单的数据模型示例:

class MyData {
  final int id;
  final String name;
  // 构造函数
  MyData({required this.id, required this.name});
  // 将MyData对象转换为Map
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
    };
  }
}

在上述代码中,我们定义了一个MyData类,它有两个字段:id和name。我们还定义了一个toMap方法,它将MyData对象转换为一个Map,这样我们就可以将它插入到数据库中。

5.2 插入数据记录

有了数据模型,我们就可以插入数据到数据库中了。以下是插入数据的示例代码:

Future<void> insertData(MyData data, Database db) async {
  try {
    // 插入数据到数据库
    await db.insert(
      'my_table',
      data.toMap(),
      // 如果插入的数据与已有数据冲突(例如,两个数据有相同的主键),则替换旧数据
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  } catch (e) {
    // 打印错误信息
    print('Failed to insert data: $e');
  }
}

在上述代码中,我们定义了一个insertData函数,它接受一个MyData对象和一个Database对象。我们调用db.insert方法来插入数据。我们传入表名my_table,以及通过data.toMap()得到的Map。如果插入的数据与已有数据冲突(例如,两个数据有相同的主键),我们选择替换旧数据,这是通过设置conflictAlgorithm为ConflictAlgorithm.replace实现的。

6. 查询数据

6.1 执行查询操作

在sqflite中,我们可以使用query方法来执行查询操作。以下是查询所有数据的示例代码:

Future<List<Map<String, dynamic>>> queryAll(Database db) async {
  // 查询所有数据
  return await db.query('my_table');
}

在上述代码中,我们定义了一个queryAll函数,它接受一个Database对象,并返回一个包含所有数据的列表。我们调用db.query方法并传入表名my_table来查询所有数据。

6.2 处理查询结果

查询结果是一个Map的列表,每个Map代表一条数据记录。我们可以将这些Map转换为我们的数据模型。以下是处理查询结果的示例代码:

Future<List<MyData>> getMyDataFromDB(Database db) async {
  // 获取所有数据
  final List<Map<String, dynamic>> maps = await queryAll(db);
  // 将Map转换为MyData对象
  return List.generate(maps.length, (i) {
    return MyData(
      id: maps[i]['id'],
      name: maps[i]['name'],
    );
  });
}

在上述代码中,我们定义了一个getMyDataFromDB函数,它接受一个Database对象,并返回一个MyData对象的列表。我们首先调用queryAll函数来获取所有数据,然后使用List.generate方法来生成一个MyData对象的列表。在生成列表的过程中,我们从每个Map中获取id和name字段,并创建一个新的MyData对象。

7. 更新数据

7.1 更新数据记录

在sqflite中,我们可以使用update方法来更新数据。以下是更新数据的示例代码:

Future<void> updateData(MyData data, Database db) async {
  // 更新数据
  await db.update(
    'my_table',
    data.toMap(),
    // 指定哪些记录应该被更新
    where: "id = ?",
    whereArgs: [data.id],
  );
}

在上述代码中,我们定义了一个updateData函数,它接受一个MyData对象和一个Database对象。我们调用db.update方法来更新数据。我们传入表名my_table,以及通过data.toMap()得到的Map。我们还指定了where和whereArgs参数,以确定哪些记录应该被更新。在这个例子中,我们更新id字段等于data.id的记录。

7.2 验证更新结果

为了验证数据是否已经被更新,我们可以再次查询数据,并检查数据是否符合预期。以下是验证更新结果的示例代码:

Future<void> verifyUpdate(MyData data, Database db) async {
  // 从数据库中获取所有数据
  List<MyData> dataList = await getMyDataFromDB(db);
  // 遍历数据列表
  for (var item in dataList) {
    // 如果找到id与待验证数据id相同的数据项
    if (item.id == data.id) {
      // 断言其name字段与待验证数据的name字段相同
      assert(item.name == data.name);
    }
  }
}

在上述代码中,我们定义了一个verifyUpdate函数,它接受一个MyData对象和一个Database对象。我们首先调用getMyDataFromDB函数来获取所有数据,然后遍历数据列表,找到id字段等于data.id的记录,并检查其name字段是否等于data.name。如果等于,那么说明更新操作成功。

8. 删除数据

8.1 删除数据记录

在sqflite中,我们可以使用delete方法来删除数据。以下是删除数据的示例代码:

Future<void> deleteData(int id, Database db) async {
  // 调用delete方法删除指定id的数据
  await db.delete(
    'my_table',
    // where子句用于指定要删除的数据
    where: "id = ?",
    whereArgs: [id],
  );
}

在上述代码中,我们定义了一个deleteData函数,它接受一个id和一个Database对象。我们调用db.delete方法来删除数据。我们传入表名my_table,并指定where和whereArgs参数,以确定哪些记录应该被删除。在这个例子中,我们删除id字段等于给定id的记录。

8.2 验证删除结果

为了验证数据是否已经被删除,我们可以再次查询数据,并检查数据是否符合预期。以下是验证删除结果的示例代码:

Future<void> verifyDelete(int id, Database db) async {
  // 从数据库中获取所有数据
  List<MyData> dataList = await getMyDataFromDB(db);
  // 遍历数据列表
  for (var item in dataList) {
    // 断言每个数据项的id都不等于已删除的数据id
    assert(item.id != id);
  }
}

在上述代码中,我们定义了一个verifyDelete函数,它接受一个id和一个Database对象。我们首先调用getMyDataFromDB函数来获取所有数据,然后遍历数据列表,检查每个记录的id字段是否不等于给定的id。如果所有记录的id字段都不等于给定的id,那么说明删除操作成功。

9. 数据库版本升级

随着应用的发展,我们可能需要修改数据库的结构,例如添加新的表或修改现有的表。这就需要升级数据库版本。在sqflite中,我们可以在打开数据库时指定版本号,并提供一个onUpgrade回调函数来处理数据库升级。

9.1 定义新的数据库版本

以下是定义新的数据库版本的示例代码:

Future<Database> createDatabase() async {
  // 获取数据库路径
  final path = await getDatabasePath('my_db.db');
  // 打开数据库,指定新的版本号
  final database = openDatabase(
    path,
    version: 2, // 新的版本号
    onCreate: (db, version) {
      return db.execute(
        "CREATE TABLE my_table(id INTEGER PRIMARY KEY, name TEXT)",
      );
    },
    // 当数据库版本升级时,执行数据库升级操作
    onUpgrade: (db, oldVersion, newVersion) {
      // 处理数据库升级...
    },
  );
  return database;
}

在上述代码中,我们在openDatabase函数中指定了新的版本号。我们还提供了一个onUpgrade回调函数,当数据库版本升级时,这个函数会被调用。

9.2 执行数据库升级操作

以下是执行数据库升级操作的示例代码:

Future<Database> createDatabase() async {
  try {
    // 获取数据库路径
    final path = await getDatabasePath('my_db.db');
    // 打开数据库,指定新的版本号
    final database = openDatabase(
      path,
      version: 2,
      onCreate: (db, version) {
        // 创建表
        return db.execute(
          "CREATE TABLE my_table(id INTEGER PRIMARY KEY, name TEXT)",
        );
      },
      // 当数据库版本升级时,执行数据库升级操作
      onUpgrade: (db, oldVersion, newVersion) {
        // 如果旧版本号小于2,为my_table表添加一个新的列age
        if (oldVersion < 2) {
          // 执行SQL语句,修改my_table表,添加新的列age
          db.execute("ALTER TABLE my_table ADD COLUMN age INTEGER");
        }
      },
    );
    // 返回数据库实例
    return database;
  } catch (e) {
    // 打印错误信息
    print('Failed to open database: $e');
    // 抛出异常
    throw e;
  }
}

在上述代码中,我们在onUpgrade回调函数中执行了一个SQL语句来修改my_table表,添加了一个新的列age。我们只在旧版本号小于2时执行这个操作,这是因为如果用户已经在版本2或更高版本的数据库中,那么age列已经存在,无需再次添加。

目录
相关文章
|
3月前
|
存储 关系型数据库 数据库
附部署代码|云数据库RDS 全托管 Supabase服务:小白轻松搞定开发AI应用
本文通过一个 Agentic RAG 应用的完整构建流程,展示了如何借助 RDS Supabase 快速搭建具备知识处理与智能决策能力的 AI 应用,展示从数据准备到应用部署的全流程,相较于传统开发模式效率大幅提升。
附部署代码|云数据库RDS 全托管 Supabase服务:小白轻松搞定开发AI应用
|
4月前
|
安全 druid Nacos
0 代码改造实现应用运行时数据库密码无损轮转
本文探讨了敏感数据的安全风险及降低账密泄漏风险的策略。国家颁布的《网络安全二级等保2.0标准》强调了企业数据安全的重要性。文章介绍了Nacos作为配置中心在提升数据库访问安全性方面的应用,并结合阿里云KMS、Druid连接池和Spring Cloud Alibaba社区推出的数据源动态轮转方案。该方案实现了加密配置统一托管、帐密全托管、双层权限管控等功能,将帐密切换时间从数小时优化到一秒,显著提升了安全性和效率。未来,MSE Nacos和KMS将扩展至更多组件如NoSQL、MQ等,提供一站式安全服务,助力AI时代的应用安全。
286 14
|
1月前
|
存储 弹性计算 Cloud Native
云原生数据库的演进与应用实践
随着企业业务扩展,传统数据库难以应对高并发与弹性需求。云原生数据库应运而生,具备计算存储分离、弹性伸缩、高可用等核心特性,广泛应用于电商、金融、物联网等场景。阿里云PolarDB、Lindorm等产品已形成完善生态,助力企业高效处理数据。未来,AI驱动、Serverless与多云兼容将推动其进一步发展。
105 8
|
11天前
|
存储 数据库 开发者
Python SQLite模块:轻量级数据库的实战指南
本文深入讲解Python内置sqlite3模块的实战应用,涵盖数据库连接、CRUD操作、事务管理、性能优化及高级特性,结合完整案例,助你快速掌握SQLite在小型项目中的高效使用,是Python开发者必备的轻量级数据库指南。
120 0
|
19天前
|
存储 弹性计算 安全
现有数据库系统中应用加密技术的不同之处
本文介绍了数据库加密技术的种类及其在不同应用场景下的安全防护能力,包括云盘加密、透明数据加密(TDE)和选择列加密。分析了数据库面临的安全威胁,如管理员攻击、网络监听、绕过数据库访问等,并通过能力矩阵对比了各类加密技术的安全防护范围、加密粒度、业务影响及性能损耗。帮助用户根据安全需求、业务改造成本和性能要求,选择合适的加密方案,保障数据存储与传输安全。
|
3月前
|
安全 Java Nacos
0代码改动实现Spring应用数据库帐密自动轮转
Nacos作为国内被广泛使用的配置中心,已经成为应用侧的基础设施产品,近年来安全问题被更多关注,这是中国国内软件行业逐渐迈向成熟的标志,也是必经之路,Nacos提供配置加密存储-运行时轮转的核心安全能力,将在应用安全领域承担更多职责。
|
2月前
|
存储 人工智能 数据库
视图是什么?为什么要用视图呢?数据库视图:定义、特点与应用
本文三桥君深入探讨数据库视图的概念与应用,从定义特点到实际价值全面解析。视图作为虚拟表具备动态更新、简化查询、数据安全等优势,能实现多角度数据展示并保持数据库重构的灵活性。产品专家三桥君还分析了视图与基表关系、创建维护要点及性能影响,强调视图是提升数据库管理效率的重要工具。三桥君通过系统讲解,帮助读者掌握这一常被忽视却功能强大的数据库特性。
421 0
|
4月前
|
SQL 数据库
软考软件评测师——数据库系统应用
本文介绍了关系数据库的基础知识与应用,涵盖候选码定义、自然连接特点、实体间关系(如1:n和m:n)、属性分类(复合、多值与派生属性)以及数据库设计规范。同时详细解析了E-R图转换原则、范式应用(如4NF)及Armstrong公理体系。通过历年真题分析,结合具体场景(如银行信用卡额度、教学管理等),深入探讨了候选键求解、视图操作规范及SQL语句编写技巧。内容旨在帮助读者全面掌握关系数据库理论与实践技能。
|
存储 数据库连接 数据库
Android数据存储:解释SQLite数据库在Android中的使用。
Android数据存储:解释SQLite数据库在Android中的使用。
221 0

热门文章

最新文章