本文从一个简单数据库示例来展示flutter使用数据库的简单的增删改查方法的基础知识
Flutter应用程序可以通过
sqflite
pub.dev上可用的插件来利用SQLite数据库 。本示例演示了sqflite
用于插入,读取,更新和删除有关各种Dog
的数据的基础知识。
如果您不熟悉SQLite和SQL语句,请在完成本示例之前,查阅 SQLite教程以了解基础知识。
本示例使用以下步骤:
- 添加依赖项。
- 定义
Dog
数据模型。 - 打开数据库。
- 创建
dogs
表。 - 将a
Dog
插入数据库。 - 检索狗列表。
- 更新
Dog
数据库中的一个。 -
Dog
从数据库中删除一个。
1.添加依赖项
要使用SQLite数据库,需导入sqflite
和path
软件包。
-
sqflite
软件包提供了与SQLite数据库进行交互的类和函数。 -
path
软件包提供了一些功能来定义将数据库存储在磁盘上的位置。
dependencies:
flutter:
sdk: flutter
sqflite: ^1.3.2+2
path: ^1.7.0
确保将软件包导入您将要使用的文件中。
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
2.定义狗数据模型
在创建用于在Dogs上存储信息的表之前,请花一些时间来定义需要存储的数据。对于此示例,定义一个Dog类,其中包含三段数据:每条狗的id
,name
,age
。
class Dog {
final int id;
final String name;
final int age;
Dog({this.id, this.name, this.age});
}
3.打开数据库
在将数据读取和写入数据库之前,要先打开与数据库的连接。这涉及两个步骤:
- 定义路径,使用
path
包下的getDatabasesPath()
组合join
获取数据库文件地址。数据库文件从 ,与组合join
从功能path
包。 - 使用中使用
sqflite
包下的openDatabase()
功能打开数据库sqflite
。
注意: 为了使用关键字await
,必须将代码放在async
函数内。应该将以下所有表函数放在内void main() async {}
。
final Future<Database> database = openDatabase(
//获取数据库对象
join(await getDatabasesPath(), 'doggie_database.db'),
);
4.创建dogs
表
接下来,创建一个表来存储有关各种狗的信息。对于此示例,创建一个名为的表,该表dogs
定义可以存储的数据。每个Dog
包含一个id
,name
和age
。因此,它们在dogs
表中表示为三列。
-
id
是Dart的int
,并且被存储为INTEGER
SQLite的数据类型。最好使用anid
作为表的主键来缩短查询和更新时间。 -
name
是Dart的String
,并且被存储为TEXT
SQLite的数据类型。 -
age
也是Dart的int
,并且被存储为INTEGER
数据类型。
有关可以存储在SQLite数据库中的可用数据类型的更多信息,请参见官方SQLite数据类型文档。
final Future<Database> database = openDatabase(
// Set the path to the database. Note: Using the `join` function from the
// `path` package is best practice to ensure the path is correctly
// constructed for each platform.
join(await getDatabasesPath(), 'doggie_database.db'),
// When the database is first created, create a table to store dogs.
onCreate: (db, version) {
// Run the CREATE TABLE statement on the database.
return db.execute(
"CREATE TABLE dogs(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)",
);
},
// Set the version. This executes the onCreate function and provides a
// path to perform database upgrades and downgrades.
version: 1,
);
5.将一只狗插入数据库
现在,您已经有了一个数据库,其中包含一个适用于存储有关各种狗的信息的表的表,是时候读写数据了。
首先,将aDog
插入dogs
表格。这涉及两个步骤:
- 将转换
Dog
成Map
- 使用
insert()
方法将储存Map
在dogs
表格中。
// Update the Dog class to include a `toMap` method.
class Dog {
final int id;
final String name;
final int age;
Dog({this.id, this.name, this.age});
// Convert a Dog into a Map. The keys must correspond to the names of the
// columns in the database.
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'age': age,
};
}
}
// Define a function that inserts dogs into the database
Future<void> insertDog(Dog dog) async {
// Get a reference to the database.
final Database db = await database;
// Insert the Dog into the correct table. You might also specify the
// `conflictAlgorithm` to use in case the same dog is inserted twice.
//
// In this case, replace any previous data.
await db.insert(
'dogs',
dog.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
// Create a Dog and add it to the dogs table.
final fido = Dog(
id: 0,
name: 'Fido',
age: 35,
);
await insertDog(fido);
6.检索狗列表
现在,一个Dog
已存储在数据库中,请在数据库中查询特定的狗或所有狗的列表。这涉及两个步骤:
-
query
对dogs
表运行 。这将返回List<Map>
。 - 将转换
List<Map>
为List<Dog>
。
// A method that retrieves all the dogs from the dogs table.
Future<List<Dog>> dogs() async {
// Get a reference to the database.
final Database db = await database;
// Query the table for all The Dogs.
final List<Map<String, dynamic>> maps = await db.query('dogs');
// Convert the List<Map<String, dynamic> into a List<Dog>.
return List.generate(maps.length, (i) {
return Dog(
id: maps[i]['id'],
name: maps[i]['name'],
age: maps[i]['age'],
);
});
}
// Now, use the method above to retrieve all the dogs.
print(await dogs()); // Prints a list that include Fido.
7.更新Dog
数据库中的
将信息插入数据库后,您可能希望稍后再更新该信息。可以使用库中的update()
方法执行此操作sqflite
。
这涉及两个步骤:
- 将狗转换成地图。
- 使用
where
子句以确保更新正确的Dog。
Future<void> updateDog(Dog dog) async {
// Get a reference to the database.
final db = await database;
// Update the given Dog.
await db.update(
'dogs',
dog.toMap(),
// Ensure that the Dog has a matching id.
where: "id = ?",
// Pass the Dog's id as a whereArg to prevent SQL injection.
whereArgs: [dog.id],
);
}
// Update Fido's age.
await updateDog(Dog(
id: 0,
name: 'Fido',
age: 42,
));
// Print the updated results.
print(await dogs()); // Prints Fido with age 42.
警告: 始终用于whereArgs
将参数传递给where
语句。这有助于防止SQL注入攻击。
请勿使用字符串插值,例如where: "id = ${dog.id}"
!
8.Dog
从数据库中删除
除了插入和更新有关Dogs的信息外,您还可以从数据库中删除Dogs。要删除数据,请使用库中的delete()
方法sqflite
。
在本节中,创建一个接受ID的函数,并从数据库中删除具有匹配ID的狗。要使此工作有效,您必须提供一个where
子句以限制要删除的记录。
Future<void> deleteDog(int id) async {
// Get a reference to the database.
final db = await database;
// Remove the Dog from the Database.
await db.delete(
'dogs',
// Use a `where` clause to delete a specific dog.
where: "id = ?",
// Pass the Dog's id as a whereArg to prevent SQL injection.
whereArgs: [id],
);
}
9.运行示例:
- 创建一个新的Flutter项目。
- 将
sqflite
和path
软件包添加到您的中pubspec.yaml
。 - 将以下代码粘贴到名为的新文件中
lib/db_test.dart
。 - 使用运行代码
flutter run lib/db_test.dart
。
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
void main() async {
// Avoid errors caused by flutter upgrade.
// Importing 'package:flutter/widgets.dart' is required.
WidgetsFlutterBinding.ensureInitialized();
// Open the database and store the reference.
final Future<Database> database = openDatabase(
// Set the path to the database. Note: Using the `join` function from the
// `path` package is best practice to ensure the path is correctly
// constructed for each platform.
join(await getDatabasesPath(), 'doggie_database.db'),
// When the database is first created, create a table to store dogs.
onCreate: (db, version) {
return db.execute(
"CREATE TABLE dogs(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)",
);
},
// Set the version. This executes the onCreate function and provides a
// path to perform database upgrades and downgrades.
version: 1,
);
Future<void> insertDog(Dog dog) async {
// Get a reference to the database.
final Database db = await database;
// Insert the Dog into the correct table. Also specify the
// `conflictAlgorithm`. In this case, if the same dog is inserted
// multiple times, it replaces the previous data.
await db.insert(
'dogs',
dog.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
Future<List<Dog>> dogs() async {
// Get a reference to the database.
final Database db = await database;
// Query the table for all The Dogs.
final List<Map<String, dynamic>> maps = await db.query('dogs');
// Convert the List<Map<String, dynamic> into a List<Dog>.
return List.generate(maps.length, (i) {
return Dog(
id: maps[i]['id'],
name: maps[i]['name'],
age: maps[i]['age'],
);
});
}
Future<void> updateDog(Dog dog) async {
// Get a reference to the database.
final db = await database;
// Update the given Dog.
await db.update(
'dogs',
dog.toMap(),
// Ensure that the Dog has a matching id.
where: "id = ?",
// Pass the Dog's id as a whereArg to prevent SQL injection.
whereArgs: [dog.id],
);
}
Future<void> deleteDog(int id) async {
// Get a reference to the database.
final db = await database;
// Remove the Dog from the database.
await db.delete(
'dogs',
// Use a `where` clause to delete a specific dog.
where: "id = ?",
// Pass the Dog's id as a whereArg to prevent SQL injection.
whereArgs: [id],
);
}
var fido = Dog(
id: 0,
name: 'Fido',
age: 35,
);
// Insert a dog into the database.
await insertDog(fido);
// Print the list of dogs (only Fido for now).
print(await dogs());
// Update Fido's age and save it to the database.
fido = Dog(
id: fido.id,
name: fido.name,
age: fido.age + 7,
);
await updateDog(fido);
// Print Fido's updated information.
print(await dogs());
// Delete Fido from the database.
await deleteDog(fido.id);
// Print the list of dogs (empty).
print(await dogs());
}
class Dog {
final int id;
final String name;
final int age;
Dog({this.id, this.name, this.age});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'age': age,
};
}
// Implement toString to make it easier to see information about
// each dog when using the print statement.
@override
String toString() {
return 'Dog{id: $id, name: $name, age: $age}';
}
}