flutter sqflite數(shù)據(jù)庫使用

flutter項目里需要存儲數(shù)據(jù)如果比較少可以用SharedPreferences,
如果存儲數(shù)據(jù)比較多 尤其需要篩選的話 我們就得用數(shù)據(jù)庫了

sqflite

sqflite 是一個 Flutter 插件,用于在 Flutter 應(yīng)用中訪問和操作 SQLite 數(shù)據(jù)庫。它提供了一系列方法來執(zhí)行 SQL 查詢、更新數(shù)據(jù)、以及管理數(shù)據(jù)庫的創(chuàng)建和版本。以下是使用 sqflite 的基本步驟:

打開數(shù)據(jù)庫

創(chuàng)建一個函數(shù)來打開數(shù)據(jù)庫,如果數(shù)據(jù)庫不存在,則創(chuàng)建它。

Future<Database> openDatabase() async {
  final databasePath = await getDatabasesPath();
  final path = join(databasePath, 'my_database.db');

  return openDatabase(
    path,
    onCreate: (db, version) {
      return db.execute(
        "CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)",
      );
    },
    version: 1,
  );
}

插入數(shù)據(jù)

使用 insert 方法向數(shù)據(jù)庫中插入數(shù)據(jù)。

Future<void> insertUser(Database db, User user) async {
  await db.insert(
    'users',
    user.toMap(),
    conflictAlgorithm: ConflictAlgorithm.replace,
  );
}

查詢數(shù)據(jù)

使用 query 方法從數(shù)據(jù)庫中查詢數(shù)據(jù)。

Future<List<User>> users(Database db) async {
  final List<Map<String, dynamic>> maps = await db.query('users');

  return List.generate(maps.length, (i) {
    return User(
      id: maps[i]['id'],
      name: maps[i]['name'],
      age: maps[i]['age'],
    );
  });
}

更新數(shù)據(jù)

使用 update 方法更新數(shù)據(jù)庫中的數(shù)據(jù)。

Future<void> updateUser(Database db, User user) async {
  await db.update(
    'users',
    user.toMap(),
    where: "id = ?",
    whereArgs: [user.id],
  );
}

刪除數(shù)據(jù)

使用 delete 方法從數(shù)據(jù)庫中刪除數(shù)據(jù)。

Future<void> deleteUser(Database db, int id) async {
  await db.delete(
    'users',
    where: "id = ?",
    whereArgs: [id],
  );
}

關(guān)閉數(shù)據(jù)庫

在適當(dāng)?shù)臅r候關(guān)閉數(shù)據(jù)庫。

await db.close();

注意事項

  • 數(shù)據(jù)模型 :考慮創(chuàng)建一個類來表示數(shù)據(jù)庫中的數(shù)據(jù)模型,這將使代碼更加清晰易懂。
  • 錯誤處理 :在進行數(shù)據(jù)庫操作時,務(wù)必處理可能出現(xiàn)的錯誤。
  • 異步操作 :數(shù)據(jù)庫操作通常是異步的,確保使用 asyncawait
  • 資源管理 :適當(dāng)時關(guān)閉數(shù)據(jù)庫,避免資源泄漏。

通過使用 sqflite,你可以在 Flutter 應(yīng)用中方便地實現(xiàn)本地數(shù)據(jù)存儲和管理。

數(shù)據(jù)庫升級

在使用 sqflite 管理數(shù)據(jù)庫時,隨著應(yīng)用的發(fā)展,你可能需要更改數(shù)據(jù)庫的結(jié)構(gòu),例如添加新的表或更改現(xiàn)有表的列。這通常涉及到數(shù)據(jù)庫的升級。在 sqflite 中,你可以通過定義不同的數(shù)據(jù)庫版本和升級邏輯來處理這些變化。

步驟

  1. 增加數(shù)據(jù)庫版本號 :在打開數(shù)據(jù)庫時,將版本號增加到新的版本。
  2. 處理升級邏輯 :在 openDatabase 方法中,使用 onUpgrade 參數(shù)來定義數(shù)據(jù)庫升級時的行為。

示例

假設(shè)你想在現(xiàn)有的數(shù)據(jù)庫中添加一個新表 orders。

final int newVersion = 2; // 假設(shè)當(dāng)前版本是 2

Database db = await openDatabase(
  path,
  version: newVersion,
  onUpgrade: (Database db, int oldVersion, int newVersion) async {
    if (oldVersion < 2) {
      // 從版本 1 升級到版本 2
      await db.execute("CREATE TABLE orders(id INTEGER PRIMARY KEY, amount INTEGER)");
    }
  },
  // 也可以添加 onDowngrade 來處理降級邏輯
);

注意事項

  • 逐步升級 :如果有多個版本,確保從每個舊版本到新版本的升級邏輯都被正確處理。
  • 備份數(shù)據(jù) :在進行結(jié)構(gòu)性更改之前,考慮備份重要數(shù)據(jù)。
  • 測試升級邏輯 :在發(fā)布新版本之前,確保測試數(shù)據(jù)庫升級邏輯,以避免數(shù)據(jù)丟失或損壞。
  • 版本控制 :合理管理數(shù)據(jù)庫版本,確保與應(yīng)用版本的兼容性。
  • 錯誤處理 :在執(zhí)行升級腳本時,確保妥善處理可能出現(xiàn)的錯誤。

通過在 sqflite 中管理數(shù)據(jù)庫版本和升級邏輯,你可以確保應(yīng)用的數(shù)據(jù)結(jié)構(gòu)隨著應(yīng)用的發(fā)展而順利演進。

我封裝了sqflite,存一個model 取出來也是一個model
需要查詢的屬性需要自己設(shè)置一個獨立屬性 ,其它屬性放到一個jsonString里面就行

首先建立一個model id是主鍵 默認(rèn)自增,也可以用項目里數(shù)據(jù)屬性的一個id代替,就不用自增了.

class NoteModel {
  //唯一di 如果需要查詢屬性比較多,這里都增加上,并在創(chuàng)建table地方增加屬性   
 //db.execute( 'create table if not exists $tableName 
 // (id integer primary key autoincrement, content text)');
  
  int? id;
  // 可以存 jsonString,使用時候 轉(zhuǎn)成model
  String? content;

  NoteModel({this.id, this.content});

  ///提供fromJson以方便將數(shù)據(jù)庫查詢結(jié)果,轉(zhuǎn)成Dart Model
  NoteModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    content = json['content'];
  }

  ///提供toJson以方便在持久化數(shù)據(jù)的時候使用
  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['id'] = id;
    data['content'] = content;
    return data;
  }
}


下面是使用方法
  //數(shù)據(jù)庫名字
  String dbName = 'test';
  //表名
  String tableName = 'tableName1';

  Database? database;
  JDTableTool? tableTool;
  //初始化
  void _doInit() async {
    // 每次TestDbContentModel結(jié)構(gòu)變化 version +1
    Database? db = storage.dateBaseMap[dbName];
    if (db != null) {
      database = db!;
    } else {
      database =
          await openDatabase(dbName, version: 1, onCreate: (db, version) {
        // 在數(shù)據(jù)庫首次創(chuàng)建時執(zhí)行的操作
      }, onUpgrade: (db, oldVersion, newVersion) async {
        // 在數(shù)據(jù)庫升級時執(zhí)行的操作
        if (oldVersion == 1 && newVersion == 2) {
          // 如果當(dāng)前數(shù)據(jù)庫版本為1,目標(biāo)版本為2,執(zhí)行操作
        }
      });
    }

    jdLog('database?.getVersion: ${await database?.getVersion()}');
    if (database != null) {
  // name TEXT, value INTEGER, num REAL; 需要查詢的屬性 必須單獨寫成屬性,如果你的map里面有唯一id 就不必要自增了
      tableTool = JDStorageTool(database!, tableName,
          'create table if not exists $tableName (id integer primary key autoincrement, content text)');
      _loadAll();
      _loadAll();
    }
  }


  void destroy() {
    tableTool?.destroy();
  }

  ///增加數(shù)據(jù)
  void _doSave(String nameValue, int age) {
    TestDbContentModel contentModel =
        TestDbContentModel.fromJson({'name': nameValue, 'age': age});
    tableTool?.saveNote(NoteModel(content: jsonEncode(contentModel.toJson())));
    _loadAll();
  }

  ///查詢數(shù)據(jù)
  void _loadAll() async {
    var list = await tableTool?.getAllNote() ?? [];
    jdLog('list.length--  ${list.length}');
    setState(() {
      noteList = list;
    });
    _getCount();
  }

  ///更新數(shù)據(jù)
  void _updateContent() {
    if (id == null || name == null) return;
    TestDbContentModel contentModel =
        TestDbContentModel.fromJson({'name': name, 'age': age});
    var model = NoteModel(id: id, content: jsonEncode(contentModel.toJson()));
    tableTool?.update(model);
    _loadAll();
  }

  ///刪除數(shù)據(jù)
  void _doDelete(NoteModel model) {
    tableTool?.deleteNote(model.id!);
    _loadAll();
  }

  ///查詢列數(shù)
  void _getCount() async {
    var count = await tableTool?.getNoteCount() ?? 0;
    setState(() {
      this.count = count;
    });
  }

具體的封裝實現(xiàn)在https://gitee.com/kuaipai/my_app.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容