Flutter之数据库的使用(sqflite_common_ffi)

2023-11-11

sqfliteFlutterSQLite插件,支持的平台有:iOS、Android、MacOS,桌面端可以使用sqflite_common_ffi,本篇文章以sqflite_common_ffi为主。

sqflite_common_ffi定义了一个全局databaseFactoryFfi允许在 Flutter 和 DartVM 上支持 Linux 和 Windows。所以databaseFactory = databaseFactoryFFi就可以带来Linux和Windows的支持。databaseFactory提供了一个直接的 API(openDatabase、deleteDatabase)。

任务要求:构建一个桌面端的任务管理软件,使用sqflite_common_ffi插件。

创建数据库

1、在你的pubspec.yaml文件中添加以下依赖:

2、封装一个数据库操作类 DBHelper()

class DBHelper {


  //定义了一个静态变量---_dbHelper,保存DBHelper类的单例实例
  static DBHelper? _dbHelper;

  //定义了一个静态方法---getInstance()获取DBHelper的单例实例
  //如果_dbHelper为空,就创建一个新的DBHelper实例
  static DBHelper getInstance() {
    if (_dbHelper == null) {
      _dbHelper = DBHelper();
    }
    return _dbHelper!;
  }

  //_db是一个Database类型的成员,用于存储数据库实例
  Database? _db;

  //数据库中的表
  static final String _ALLTask = "_ALLTask"; //所有任务

  //database是一个异步getter,它返回数据库实例。如果_db为空,就调用initDB方法初始化数据库。
  Future<Database> get database async {
    if (_db != null) {
      return _db!;
    }
    _db = await initDB();
    return _db!;
  }

}

3、初始化数据库操作  initDB()

a.初始化数据库sqfliteFfiInit();

b.获取databaseFactoryFfi对象

c.使用databaseFactoryFfi 对象来打开数据库,语句:databaseFactory.openDatabase()

String Path.(获取数据库的默认位置,最好使用"path_provider"策略)

path_provider的使用:

1、添加依赖

2、在需要的文件中导入包

import 'package:path/path.dart' as path;

openDatabaseOptions(打开数据库操作)的某些属性:

  /// Specify the expected version.
  int? version;

  /// called right after opening the database.(打开数据库后立即调用)
  OnDatabaseConfigureFn? onConfigure;

  /// Called when the database is created.(数据库创建时的回调函数)
  OnDatabaseCreateFn? onCreate;

  /// Called when the database is upgraded.(数据库升级时调用)
  OnDatabaseVersionChangeFn? onUpgrade;

  /// Called when the database is downgraded.(数据库降级时调用)
  ///
  /// Use [onDatabaseDowngradeDelete] for re-creating the database
(使用 [onDatabaseDowngradeDelete] 重新创建数据库)
  OnDatabaseVersionChangeFn? onDowngrade;

  /// Called after all other callbacks have been called.(在调用所有其他回调后调用)
  OnDatabaseOpenFn? onOpen;

  /// Open the database in read-only mode (no callback called).(以只读模式打开数据库(不调用回调)。)
  late bool readOnly;

  /// The existing single-instance (hot-restart)(现有单实例(热重启))
  late bool singleInstance;

 //初始化数据库
  initDB()async{
    //1、初始化数据库
    sqfliteFfiInit();
   
    //2、获取databaseFactoryFfi对象
    var databaseFactory = databaseFactoryFfi;
    
    //3、创建数据库
    return await databaseFactory.openDatabase(

        //数据库路径
        path.join(await databaseFactory.getDatabasesPath(), "TO-DO.db"),

        //打开数据库操作
        options: OpenDatabaseOptions(
          //版本
          version: 5,
          //创建时操作
          onCreate: (db,version)async{
            print("创建数据库");
            return await db.execute(
              "CREATE TABLE $_ALLTask ("
                  "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                  "content TEXT,"
                  "ownType STRING,"
                  "startDate STRING,"
                  "endDate STRING,"
                  "createTime STRING,"
                  "completeTime STRING,"
                  "repeat STRING,"
                  "isCompleted INTEGER"
                  ")"
            );
          }
        )
      );
  }

至此,数据库创建完成。

数据库操作

增加:

1、Database.insert
Future<int> insert(
            String table, //表名
            Map<String, Object?> values,//插入的数据
            {String? nullColumnHack,
             ConflictAlgorithm? conflictAlgorithm
            }
            );
//插入数据
  Future<int>insert(Task task)async{
    Database db=await database;
    print("insert function called");
    print("插入的数据:${task.toJson()}");
    /*insert方法会返回最后的行id*/
    return await db.insert(_ALLTask, task.toJson());
  }
2、Database.rawInsert
 Future<int> rawInsert(String sql, [List<Object?>? arguments]);
//插入数据——法二 rawInsert
  Future<int> rawInsert(Task task) async{
    
    Database db=await database;
    
    return await db.rawInsert(
        "INSERT INTO $_ALLTask (content, ownType, startDate, endDate, createTime,             
         completeTime, repeat, isCompleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",[task.content,task.ownType,task.startDate,task.endDate,task.createTime,task.completeTime,task.repeat,task.isCompleted]);
  }

删除:

使用 whereArgs 将参数传递给 where 语句。有助于防止 SQL 注入攻击 

 Future<int> delete(String table, {String? where, List<Object?>? whereArgs});
Future delete(Task task)async{
    Database db=await database;
    print("delete function called!");
    await db.delete(_ALLTask,where: "id=?",whereArgs: [task.id]);
  }

修改:

1、Database.update
Future<int> update(String table, Map<String, Object?> values,
      {String? where,
      List<Object?>? whereArgs,
      ConflictAlgorithm? conflictAlgorithm});
//修改任务内容(全部数据)
  Future update(Task task)async{
  
    Database db=await database;
    return db.update(_ALLTask, task.toJson(), where: 'id=?', whereArgs: [task.id]);
  }
2、Database.rawUpdate
 Future<int> rawUpdate(String sql, [List<Object?>? arguments]);
Future rawUpdate(Task task,newDate) async{

    Database db=await database;
    return db.rawUpdate(
      '''
      UPDATE $_ALLTask
      SET createTime=?
      WHERE id=?
      ''',
      [newDate,task.id]
    );

 查询:

1、Database.query
Future<List<Map<String, Object?>>> query(String table,
      {bool? distinct,
      List<String>? columns,
      String? where,
      List<Object?>? whereArgs,
      String? groupBy,
      String? having,
      String? orderBy,
      int? limit,
      int? offset});
  //查询数据
  /*查询到后返回的是一个List<Map<String,Object?>>类型的列表,每一个元素都是Map<String,Object?>
   *result就是List<Map<String,Object?>>类型的列表
   *result.map((taskMap) => Task.fromJson(taskMap))=======>遍历每一个元素,将每一个元素都执行 
   *给定的函数,此处是Task.fromJson(taskMap),然后返回一个新的迭代器
   *所以这个迭代器里的每一个元素都转换成了Task类型
   *.toList();将这个迭代器转换成列表
   * 所以最后就返回了一个Task类型的列表  */

  Future<List<Task>> query() async{
    Database db=await database;
    print("query function called!");
    var result=await db.query(_ALLTask);
   /*此时返回的是一个List<Task>类型*/
    return result.map((taskMap) => Task.fromJson(taskMap)).toList();
    
  }
2、Database.rawQuery
Future<List<Map<String, Object?>>> rawQuery(
      String sql,
      [List<Object?>? arguments]);
Future<List<Task>> rawquery() async{
    Database db=await database;
    print("query function called!");
    var result=await db.rawQuery("SELECT * FROM $_ALLTask ");
   /*此时返回的是一个List<Task>类型*/
    return result.map((taskMap) => Task.fromJson(taskMap)).toList();
    
  }

查询时排序:

ASC:表示按升序排序。 DESC:表示按降序排序。

var result=await db.query(_ALLTask,orderBy: "datetime(createTime) ASC");
var result=await db.rawQuery("SELECT * FROM $_ALLTask ORDER BY datetime(createTime) DESC");

此时我想按照字段 createTime进行升序、降序。但是字段createTime是String类型。

SQLite中支持多种日期时间格式,但是建议使用ISO 8601格式来存储日期时间值。ISO 8601是一种国际标准,用于表示日期、时间和日期时间值。它的格式如下:

YYYY-MM-DDTHH:MM:SS.SSSZ

其中,YYYY表示年份,MM表示月份,DD表示日期,T表示时间分隔符,HH表示小时,MM表示分钟,SS表示秒,.SSS表示毫秒(可选),Z表示时区偏移量

我的时间格式如下:2023-07-12--11:23:02

String timeStr = "2023-07-12--11:23:02";

//首先使用replaceAll()方法将时间字符串中的--替换为T,以便它符合ISO 8601格式
//使用DateTime.parse()方法将字符串解析为日期时间类型。
DateTime dateTime = DateTime.parse(timeStr.replaceAll("--", "T"));

//使用toIso8601String()方法将日期时间类型格式化为ISO 8601字符串
String iso8601Str = dateTime.toIso8601String();

print("${iso8601Str}");

最后打印出的数据:2023-07-12T15:26:31.000

在现有数据表中插入新列并设置默认值

Future<void> addColumn() async {
  Database db = await database;
  await db.execute("ALTER $_ALLTask task ADD COLUMN priority INTEGER DEFAULT 0");
}

 默认值此时为0,如果不设置默认值的话,默认值全部为null

在priority默认值全部为null的时候修改为0:

//设置新列的默认值
  Future setdefaultValue()async{
    Database db = await database;
    await db.execute("UPDATE $_ALLTask  SET priority = ? WHERE priority IS ?",[0,null]);
  }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flutter之数据库的使用(sqflite_common_ffi) 的相关文章

随机推荐

  • SQL注入---联合注入

    Union联合注入攻击 1 联合注入的思路 会显示输出内容时 才考虑使用Union注入 可以在输入框中或者 URL 中输入内容 如果不能在输入框内输入内容 则需要使用 Burp suite 使用 重发器 修改 id 中的内容进行爆破数据 l
  • C++中实现Stack

    栈的实现 栈 示例代码 开发环境 运行结果 栈 栈本着先进后出的原则 来存取数据 作为数据结构中的一种 这里不多介绍相关栈 仅以此文记录C 中栈的实现 可帮助提升编程能力与对栈的理解 示例代码 直接上代码 SeqStack h pragma
  • Windows密码破解

    这里主要介绍两种方法来破解Windows的开机密码 一 利用五次shift漏洞来对win7 win10进行破解 此方法只适用于win7或者早期的win10 此方法主要是利用Windows开机时默认按五次shift键会启用粘贴键程序如下图 我
  • 手动推导LogisticRegression建模结果

    usr bin env python3 coding UTF 8 Date 2023 8 25 15 51 Author HELIN import numpy as np from sklearn model selection impor
  • 如何从Windows切换到Linux

    作者 栈栈 链接 CU技术社区 微软已经马上准备在2020年1月份终止对Windows 7的支持 这意味着您将不再获得bug修复或安全更新 如果您是Windows 7的最终支持者之一 并且不想陷入一个不安全的系统 则可以选择 升级到Wind
  • Verilog功能模块——Uart收发

    摘要 本文分享了一种通用的Uart收发模块 可实现Uart协议所支持的任意波特率 任意位宽数据 5 8 任意校验位 无校验 奇校验 偶校验 1校验 0校验 任意停止位 1 1 5 2 的数据传输 此模块需要搭配FIFO使用 以消除发送端和接
  • 最新AI创作系统ChatGPT网站源码+详细图文搭建教程/支持GPT-4/支持AI绘画/Prompt应用/访客体验功能

    一 SparkAI创作系统 如何搭建部署AI创作ChatGPT系统呢 小编这里写一个详细图文教程吧 SparkAi使用Nestjs和Vue3框架技术 持续集成AI能力到AIGC系统 1 1 程序核心功能 程序已支持ChatGPT3 5 4
  • Python:安装Flask web框架hello world示例

    安装easy install pip install distribute 安装pip easy install pip 安装 virtualenv pip install virtualenv 激活Flask pip install Fl
  • 搭建私人图床结合内网穿透实现公网访问,让您的摄影作品连接世界

    文章目录 1 树洞外链网站搭建 1 1 下载安装树洞外链 1 2 树洞外链网页测试 1 3 cpolar的安装和注册 2 本地网页发布 2 1 Cpolar临时数据隧道 2 2 Cpolar稳定隧道 云端设置 2 3 Cpolar稳定隧道
  • Select、Poll、Epoll的使用和区别,多种IO的区别

    目录 一 四种IO分类 二 I O多路复用select 三 I O多路复用Poll 四 I O多路复用Epoll 五 三种多路复用的区别总结 1 支持一个进程所能打开的最大连接数 2 fd剧增后带来的IO效率问题 3 消息传递方式 4 索引
  • 一、PyTorch基础:Tensor基础操作

    1 1Tensor Tensor 又名张量 读者可能对这个名词似曾相识 因它不仅在PyTorch中出现过 它也是Theano TensorFlow Torch和MxNet中重要的数据结构 关于张量的本质不乏深度的剖析 但从工程角度来讲 可简
  • SQL注入-报错注入

    页面没有显示位 但有数据库的报错信息时 可使用报错注入 报错注入是最常用的注入方式 也是使用起来最方便 我觉得 的一种注入方式 updatexml 1 3 第二个参数包含特殊字符时 数据库会报错 并将第二个参数的内容显示在报错内容中 返回结
  • 机器学习——特征工程(3分钟的超详细介绍)

    目录 1 什么是特征工程 2 数据预处理和特征处理 2 1 数据预处理 2 2 特征处理 3 特征降维 3 0 什么是特征降维 3 1 特征选择 3 2 线性降维 3 2 1 主成分分析法 PCA 3 2 2 线性判别分析法 LDA 1 什
  • 使用ESCAPE处理模糊查询%的问题

    前言 在模糊查询时 如果要查询的内容中有 比例 小明 如果不做处理 那么就会查询到所以的小明相关的数据 不能只查询到小明 的数据 1 创建工具类 工具类 public class StringUtils private static fin
  • QT关于QGIS3.26的二次开发

    目录 1 使用平台以及版本 2 显示一张tif格式的图片 3 代码的具体分析 4 一点基础知识 5 其他代码 1 使用平台以及版本 VS 2022 编译器MSVC2019 QT版本 5 15 2 系统 win10 QGIS版本 3 26 9
  • Raspberry系统管理 —— 安装和配置OpenVINO

    文章目录 什么是OpenVINO 下载测试用例 加速自己的模型 什么是OpenVINO OpenVINO Open Visual Inference and Neural Network Optimization 是一个用于视觉推理和神经网
  • 【计算机视觉

    文章目录 一 2D open vocabulary object detection的发展和研究现状 二 基于大规模外部图像数据集 2 1 OVR CNN Open Vocabulary Object Detection Using Cap
  • PyQt学习笔记-信号与槽

    PyQt学习笔记 信号与槽 一 基本概念 二 编辑信号与槽 三 自定义槽 四 将自定义的槽函数连接到信号 五 多窗口设计 1 设置启动窗口 2 窗口之间的关联 一 基本概念 信号与槽是Qt的核心机制 也是PyQt5编程时对象之间通信的基础
  • JDBC操作MySQL5日期类型字段的问题解决方法

    JDBC操作MySQL5日期类型字段的问题解决方法 由于日期数据的特殊性和多样性 以及不同的数据库 编程语言对日期的定义和处理方式差别 导致了日期处理的复杂性 和多样性 流行的Hibernate iBatis等持久化框架从中解决了各种Jav
  • Flutter之数据库的使用(sqflite_common_ffi)

    sqflite是Flutter的SQLite插件 支持的平台有 iOS Android MacOS 桌面端可以使用sqflite common ffi 本篇文章以sqflite common ffi为主 sqflite common ffi