Flutter database operation is enough to read this article

Flutter common database operation library

Flutter is a cross-platform mobile application development framework that supports the use of multiple types of databases for data storage and management. The use of databases in Flutter usually needs to rely on third-party libraries. The following are some commonly used Flutter database libraries:

  • sqflite: It is a Flutter plug-in for SQLite database, which provides an API interface similar to SQLite in Android and supports basic CRUD operations.
  • firebase_database: is a real-time NoSQL database provided by Google, which can be used for data storage and synchronization of Flutter applications.
  • hive: is a fast, lightweight key-value pair database with high performance and low latency, suitable for local data storage in Flutter applications.

The most commonly used sqflite introduction

Introduction

sqflite is a Flutter plugin for SQLite database, which provides an API interface similar to SQLite in Android and supports basic CRUD operations. It is one of the most widely used local database libraries in Flutter, which can be used to store the local data of the application. Sqflite is lightweight, high performance, and easy to use, making it suitable for small applications or those that require simple local data storage.

example

Below is a sample code using the sqflite library, demonstrating how to create and use an SQLite database in a Flutter application:

  1. Add dependencies of the sqflite library:

Add the dependency of the sqflite library to the pubspec.yaml file of the Flutter project:

dependencies:
  sqflite: ^2.2.8+4
  1. Create a database:

To create a database example in a Flutter application, a my_database.dbSQLite database named SQLite can be created by executing the following code:

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

class MyDatabase {
  static final MyDatabase _instance = MyDatabase._internal();

  factory MyDatabase() => _instance;

  static Database _database;

  MyDatabase._internal();

  Future<Database> get database async {
    if (_database != null) return _database;

    _database = await _initDatabase();
    return _database;
  }

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

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

In the above code, we use the methods sqflitein the library openDatabaseto create the database and specify the database file path. We also provide a onCreatecallback function to perform some initialization operations when creating the database, such as creating tables and so on.

  1. Insert data:

The following is a sample code that demonstrates how to insert a piece of data into the database:

final db = await MyDatabase().database;
await db.insert(
  'users',
  {'name': 'John'},
  conflictAlgorithm: ConflictAlgorithm.replace,
);

In the above code, we first obtain a database instance, and then use insertthe method to usersinsert a piece of data into the table named. We store the data as a Map object where the keys are the column names and the values ​​are the values ​​to be inserted. If there are already records with the same primary key in the table, we use conflictAlgorithmparameters to specify the conflict handling strategy, which is used here ConflictAlgorithm.replaceto indicate that the old data is replaced with new data.

  1. Query data:

Here is a sample code that demonstrates how to query data from the database:

final db = await MyDatabase().database;
final List<Map<String, dynamic>> users = await db.query('users');

In the above code, we first obtain a database instance, and then use querythe method to query usersall the data in the table named. The query result will return a list containing multiple Map objects, where each Map object represents a record, the key is the column name, and the value is the corresponding value.

  1. update data:

Here is a sample code that demonstrates how to update data in the database:

final db = await MyDatabase().database;
await db.update(
  'users',
  {'name': 'Mary'},
  where: 'id = ?',
  whereArgs: [1],
);

In the above code, we first obtain a database instance, and then use updatethe method to update usersa piece of data in the table named. We use wherethe parameter to specify the condition of the record to be updated, which is represented idas 1 here, and use whereArgsthe parameter to specify the parameter value in the condition. We store the data to be updated as a Map object, where the key is the column name and the value is the value to be updated.

  1. delete data:

Here is a sample code that demonstrates how to delete data from the database:

final db = await MyDatabase().database;
await db.delete(
  'users',
  where: 'id = ?',
  whereArgs: [1],
);

In the above code, we first obtain a database instance, and then use deletethe method to delete usersa piece of data in the table named. We use wherethe parameter to specify the condition of the record to be deleted, which is represented idas 1 here, and use whereArgsthe parameter to specify the parameter value in the condition.

Relying on sqflite, the singleton mode encapsulates a sqlite operation class

import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:learning/model/task_model.dart';

class DatabaseHelper {
  DatabaseHelper._(); //单例模式

  static final DatabaseHelper db = DatabaseHelper._();
  static Database? _database;

  Future<Database?> get database async {
    _database ??= await initDb();
    return _database;
  }

  //init database and open it
  Future<Database> initDb() async {
    print("initDb");
    Directory documentDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentDirectory.path, 'yytimer.db');
    print("initDb ${path}");

    Database db = await openDatabase(path, version: 1, onOpen: (db) async {
      // 等待表创建完成
      await db.execute(
          'CREATE TABLE IF NOT EXISTS timerdata (id INTEGER PRIMARY KEY, title TEXT, sptime INTEGER, retime INTEGER, cycle INTEGER, setsgap INTEGER, groups INTEGER)');
    });
    return db;
  }

  //insert database
  Future<int?> insert(Task task) async {
    print('insert data Saving Task...');
    final db = await database; // 确保database在上下文中定义

    try {
      var result = await db?.rawInsert(
          'INSERT OR REPLACE INTO timerdata (id,title,sptime,retime, cycle,setsgap,groups) VALUES (?,?,?,?,?,?,?)',
          [
            task.id,
            task.title,
            task.sptime,
            task.retime,
            task.cycle,
            task.setsgap,
            task.groups
          ]);
      print('insert data id timerdata saved! ${task.id}, ${task.title}, ${task.sptime}, ${task.retime},${task.cycle}, ${task.setsgap}, ${task.groups}');
      return result;
    } on DatabaseException catch (e) {
      print(e);
      return -1;
    }
  }

  //query database
  Future<List<Task>> getAll() async {
    print('getAll database...');
    var db = await database;
    var query = await db?.query('timerdata', orderBy: 'id DESC');

    List<Task> tasks =
        query!.isNotEmpty ? query.map((t) => Task.fromMap(t)).toList() : [];
    print('getAll in database: ${tasks.length} , ${tasks[0].title},${tasks[1].title}');
    return tasks;
  }

  //delete sql by id
  Future<void> delete(int id) async {
    var db = await database;
    await db?.rawDelete('DELETE FROM timerdata WHERE id = ?', [id]);
  }

  //delete sql by title
  Future<void> deleteByTitle(String title) async {
    var db = await database;
    await db?.rawDelete('DELETE FROM timerdata WHERE title = ?', [title]);
  }

  //update database by id
  Future<void> updateDatabase(Task task) async {
    final db = await database;
    await db?.update(
      'timerdata',
      task.toMap(),
      where: "id = ?",
      whereArgs: [task.id],
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }

  //update database by title
  Future<void> updateDatabaseByTitle(Task task) async {
    final db = await database;
    await db?.update(
      'timerdata',
      task.toMap(),
      where: "title = ?",
      whereArgs: [task.title],
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }
}

In initDb(), you can use await db.execute() to wait for the creation of the database table to be completed, avoiding problems in using the database before creating the table.
In the insert() method, you can use the INSERT OR REPLACE statement to implement insert or update operations to avoid inserting duplicate data.
In the getAll() method, you can use db!.query('timerdata', orderBy: 'id DESC') to get all the data in reverse order by id, which can avoid the operation of sorting after getting the data.
In the updateDatabase() and updateDatabaseByTitle() methods, you can use the conflictAlgorithm parameter of the update() method to implement insert or update operations to avoid the problem of updating duplicate data.

illustrate

initDb Description

onCreate is the callback function called when the database is opened for the first time to create database tables and initialize data. In Dart's sqflite library, the signature of the onCreate callback function is (Database db, int version), where the db parameter is the opened database object, and the version parameter is the version number of the database.

In the onCreate callback function, we can use the db.execute() method to execute SQL statements to create tables and initialize data. For example, in the following code:

Database db = await openDatabase(path, version: 1, onCreate: (Database db, int version) async {
    
    
  await db.execute('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)');
  await db.execute('INSERT INTO users (name) VALUES ("Alice")');
});

We created a table called users and inserted a record. Specifically, we used the CREATE TABLE IF NOT EXISTS statement to create a users table, which has two fields: id and name, where id is the primary key and name is the text type. Then, we use the INSERT INTO statement to insert a record into the users table, the name field of the record is "Alice"``onCreate is the callback function called when the database is opened for the first time, and is used to create the database table and initialize the data. In Dart's sqflite library, the signature of the onCreate callback function is (Database db, int version), where the db parameter is the opened database object, and the version parameter is the version number of the database.

conflictAlgorithm description

conflictAlgorithmIs the resolution strategy when conflicts (such as violations of unique constraints) occur when data is inserted or updated. In the Dart sqflitelibrary, there are the following four conflict resolution strategies:

  1. ConflictAlgorithm.rollback: Rollback the transaction, discarding all changes.
  2. ConflictAlgorithm.abort: Abort the current operation, but do not roll back the transaction.
  3. ConflictAlgorithm.fail: Abandon the current operation, but do not roll back the transaction, and throw an exception.
  4. ConflictAlgorithm.replace: Replace old data, or insert new data, to resolve conflicts.

In the code, ConflictAlgorithm.replacethe function is to replace the old data with the new data if a conflict occurs when inserting or updating data. This strategy can guarantee the uniqueness of the data and will not throw exceptions. If the data does not exist, the new data is directly inserted, and if the data already exists, the old data is replaced with the new data.

For example, in the code above, parameters are used in the updateDatabase()and methods to avoid updating or inserting duplicate data. If data with the same id or title already exists in the table, the old data will be replaced with the new data, otherwise the new data will be inserted directly.updateDatabaseByTitle()conflictAlgorithm: ConflictAlgorithm.replace

The interface written before, the effect of saving the data in the database is as follows:
insert image description here

Guess you like

Origin blog.csdn.net/yikezhuixun/article/details/130882658
Recommended