Как сделать вставку базы данных с помощью SQFlite во Flutter

Как вставить данные в базу данных во Flutter с помощью плагина SQFlite?

Есть ряд вопросов для решения проблем, но я не смог найти канонического ответа. Мой ответ ниже.

1 ответ

Решение

Добавьте зависимости

открыто pubspec.yaml и в разделе зависимостей добавьте следующие строки:

sqflite: ^1.0.0
path_provider: ^0.4.1

sqflite плагин SQFlite, конечно, и path_provider поможет нам получить каталог пользователей на Android и iPhone.

Создайте вспомогательный класс базы данных

Я держу глобальную ссылку на базу данных в одноэлементном классе. Это предотвратит проблемы параллелизма и утечки данных (это то, что я слышу, но скажите мне, если я ошибаюсь). Здесь вы также можете добавить вспомогательные методы (например, insert) для доступа к базе данных.

Создайте новый файл с именем database_helper.dart и вставьте следующий код:

import 'dart:io' show Directory;
import 'package:path/path.dart' show join;
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart' show getApplicationDocumentsDirectory;

class DatabaseHelper {

  static final _databaseName = "MyDatabase.db";
  static final _databaseVersion = 1;

  static final table = 'my_table';

  static final columnId = '_id';
  static final columnName = 'name';
  static final columnAge = 'age';

  // make this a singleton class
  DatabaseHelper._privateConstructor();
  static final DatabaseHelper instance = DatabaseHelper._privateConstructor();

  // only have a single app-wide reference to the database
  static Database _database;
  Future<Database> get database async {
    if (_database != null) return _database;
    // lazily instantiate the db the first time it is accessed
    _database = await _initDatabase();
    return _database;
  }

  // this opens the database (and creates it if it doesn't exist)
  _initDatabase() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, _databaseName);
    return await openDatabase(path,
        version: _databaseVersion,
        onCreate: _onCreate);
  }

  // SQL code to create the database table
  Future _onCreate(Database db, int version) async {
    await db.execute('''
          CREATE TABLE $table (
            $columnId INTEGER PRIMARY KEY,
            $columnName TEXT NOT NULL,
            $columnAge INTEGER NOT NULL
          )
          ''');
  }
}

Вставить данные

Мы будем использовать асинхронный метод для нашей вставки:

  _insert() async {

    // get a reference to the database
    // because this is an expensive operation we use async and await
    Database db = await DatabaseHelper.instance.database;

    // row to insert
    Map<String, dynamic> row = {
      DatabaseHelper.columnName : 'Bob',
      DatabaseHelper.columnAge  : 23
    };

    // do the insert and get the id of the inserted row
    int id = await db.insert(DatabaseHelper.table, row);

    // show the results: print all rows in the db
    print(await db.query(DatabaseHelper.table));
  }

Заметки

  • Вам придется импортировать DatabaseHelper класс и sqflite если вы находитесь в другом файле (например, main.dart).
  • Плагин SQFlite использует Map<String, dynamic> сопоставить имена столбцов с данными в каждой строке.
  • Мы не указали id, SQLite автоматически увеличивает его для нас.

Необработанная вставка

SQFlite также поддерживает выполнение необработанной вставки. Это означает, что вы можете использовать строку SQL. Давайте вставим ту же строку снова, используя rawInsert(),

db.rawInsert('INSERT INTO my_table(name, age) VALUES("Bob", 23)');

Конечно, нам не хотелось бы жестко кодировать эти значения в строку SQL, но мы также не хотели бы использовать интерполяцию, подобную этой:

String name = 'Bob';
int age = 23;
db.rawInsert('INSERT INTO my_table(name, age) VALUES($name, $age)'); // Dangerous!

Это открыло бы нас для атак инъекций SQL. Вместо этого мы можем использовать привязку данных следующим образом:

db.rawInsert('INSERT INTO my_table(name, age) VALUES(?, ?)', [name, age]);

[name, age] заполнены для заполнителей вопросительного знака в (?, ?), Имена таблиц и столбцов безопаснее использовать для интерполяции, поэтому мы могли бы сделать это наконец:

String name = 'Bob';
int age = 23;
db.rawInsert(
    'INSERT INTO ${DatabaseHelper.table}'
        '(${DatabaseHelper.columnName}, ${DatabaseHelper.columnAge}) '
        'VALUES(?, ?)', [name, age]);

Дополнительный код

Для удобства копирования и вставки приведен код макета для main.dart:

import 'package:flutter/material.dart';
import 'package:flutter_db_operations/database_helper.dart';
import 'package:sqflite/sqflite.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SQFlite Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('sqflite'),
      ),
      body: RaisedButton(
        child: Text('insert', style: TextStyle(fontSize: 20),),
        onPressed: () {_insert();},
      ),
    );
  }

  _insert() async {

    // get a reference to the database
    // because this is an expensive operation we use async and await
    Database db = await DatabaseHelper.instance.database;

    // row to insert
    Map<String, dynamic> row = {
      DatabaseHelper.columnName : 'Bob',
      DatabaseHelper.columnAge  : 23
    };

    // do the insert and get the id of the inserted row
    int id = await db.insert(DatabaseHelper.table, row);

    // raw insert
    //
    //  String name = 'Bob';
    //  int age = 23;
    //  int id = await db.rawInsert(
    //    'INSERT INTO ${DatabaseHelper.table}'
    //          '(${DatabaseHelper.columnName}, ${DatabaseHelper.columnAge}) '
    //          'VALUES(?, ?)', [name, age]);

    print(await db.query(DatabaseHelper.table));
  }

}

Продолжается

  1. попасть в pubspec.yaml

  2. Добавить

      dependency:  
          sqflite: any,   
          path_provider: any,   
          intl: ^0.15.7
  1. затем щелкните получить пакет и обновить пакет
Другие вопросы по тегам