本文從一個(gè)簡單數(shù)據(jù)庫示例來展示flutter使用數(shù)據(jù)庫的簡單的增刪改查方法的基礎(chǔ)知識
Flutter應(yīng)用程序可以通過
sqflite
pub.dev上可用的插件來利用SQLite數(shù)據(jù)庫 蔚约。本示例演示了sqflite
用于插入提前,讀取澜掩,更新和刪除有關(guān)各種Dog
的數(shù)據(jù)的基礎(chǔ)知識牺陶。
如果您不熟悉SQLite和SQL語句仍稀,請?jiān)谕瓿杀臼纠埃殚?SQLite教程以了解基礎(chǔ)知識会钝。
本示例使用以下步驟:
- 添加依賴項(xiàng)向臀。
- 定義
Dog
數(shù)據(jù)模型。 - 打開數(shù)據(jù)庫架谎。
- 創(chuàng)建
dogs
表炸宵。 - 將a
Dog
插入數(shù)據(jù)庫。 - 檢索狗列表谷扣。
- 更新
Dog
數(shù)據(jù)庫中的一個(gè)土全。 -
Dog
從數(shù)據(jù)庫中刪除一個(gè)捎琐。
1.添加依賴項(xiàng)
要使用SQLite數(shù)據(jù)庫,需導(dǎo)入sqflite
和path
軟件包裹匙。
-
sqflite
軟件包提供了與SQLite數(shù)據(jù)庫進(jìn)行交互的類和函數(shù)瑞凑。 -
path
軟件包提供了一些功能來定義將數(shù)據(jù)庫存儲(chǔ)在磁盤上的位置。
dependencies:
flutter:
sdk: flutter
sqflite: ^1.3.2+2
path: ^1.7.0
確保將軟件包導(dǎo)入您將要使用的文件中概页。
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
2.定義狗數(shù)據(jù)模型
在創(chuàng)建用于在Dogs上存儲(chǔ)信息的表之前籽御,請花一些時(shí)間來定義需要存儲(chǔ)的數(shù)據(jù)。對于此示例惰匙,定義一個(gè)Dog類技掏,其中包含三段數(shù)據(jù):每條狗的id
,name
项鬼,age
哑梳。
class Dog {
final int id;
final String name;
final int age;
Dog({this.id, this.name, this.age});
}
3.打開數(shù)據(jù)庫
在將數(shù)據(jù)讀取和寫入數(shù)據(jù)庫之前,要先打開與數(shù)據(jù)庫的連接绘盟。這涉及兩個(gè)步驟:
- 定義路徑鸠真,使用
path
包下的getDatabasesPath()
組合join
獲取數(shù)據(jù)庫文件地址。數(shù)據(jù)庫文件從 龄毡,與組合join
從功能path
包弧哎。 - 使用中使用
sqflite
包下的openDatabase()
功能打開數(shù)據(jù)庫sqflite
。
注意: 為了使用關(guān)鍵字await
稚虎,必須將代碼放在async
函數(shù)內(nèi)。應(yīng)該將以下所有表函數(shù)放在內(nèi)void main() async {}
偎捎。
final Future<Database> database = openDatabase(
//獲取數(shù)據(jù)庫對象
join(await getDatabasesPath(), 'doggie_database.db'),
);
4.創(chuàng)建dogs
表
接下來蠢终,創(chuàng)建一個(gè)表來存儲(chǔ)有關(guān)各種狗的信息。對于此示例茴她,創(chuàng)建一個(gè)名為的表寻拂,該表dogs
定義可以存儲(chǔ)的數(shù)據(jù)。每個(gè)Dog
包含一個(gè)id
丈牢,name
和age
祭钉。因此,它們在dogs
表中表示為三列己沛。
-
id
是Dart的int
慌核,并且被存儲(chǔ)為INTEGER
SQLite的數(shù)據(jù)類型。最好使用anid
作為表的主鍵來縮短查詢和更新時(shí)間申尼。 -
name
是Dart的String
垮卓,并且被存儲(chǔ)為TEXT
SQLite的數(shù)據(jù)類型。 -
age
也是Dart的int
师幕,并且被存儲(chǔ)為INTEGER
數(shù)據(jù)類型粟按。
有關(guān)可以存儲(chǔ)在SQLite數(shù)據(jù)庫中的可用數(shù)據(jù)類型的更多信息,請參見官方SQLite數(shù)據(jù)類型文檔。
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.將一只狗插入數(shù)據(jù)庫
現(xiàn)在灭将,您已經(jīng)有了一個(gè)數(shù)據(jù)庫疼鸟,其中包含一個(gè)適用于存儲(chǔ)有關(guān)各種狗的信息的表的表,是時(shí)候讀寫數(shù)據(jù)了庙曙。
首先空镜,將aDog
插入dogs
表格。這涉及兩個(gè)步驟:
- 將轉(zhuǎn)換
Dog
成Map
- 使用
insert()
方法將儲(chǔ)存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.檢索狗列表
現(xiàn)在姑裂,一個(gè)Dog
已存儲(chǔ)在數(shù)據(jù)庫中,請?jiān)跀?shù)據(jù)庫中查詢特定的狗或所有狗的列表男旗。這涉及兩個(gè)步驟:
-
query
對dogs
表運(yùn)行 舶斧。這將返回List<Map>
。 - 將轉(zhuǎn)換
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
數(shù)據(jù)庫中的
將信息插入數(shù)據(jù)庫后茴厉,您可能希望稍后再更新該信息∈踩伲可以使用庫中的update()
方法執(zhí)行此操作sqflite
矾缓。
這涉及兩個(gè)步驟:
- 將狗轉(zhuǎn)換成地圖。
- 使用
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
將參數(shù)傳遞給where
語句嗜闻。這有助于防止SQL注入攻擊。
請勿使用字符串插值桅锄,例如where: "id = ${dog.id}"
琉雳!
8.Dog
從數(shù)據(jù)庫中刪除
除了插入和更新有關(guān)Dogs的信息外,您還可以從數(shù)據(jù)庫中刪除Dogs友瘤。要?jiǎng)h除數(shù)據(jù)翠肘,請使用庫中的delete()
方法sqflite
。
在本節(jié)中辫秧,創(chuàng)建一個(gè)接受ID的函數(shù)束倍,并從數(shù)據(jù)庫中刪除具有匹配ID的狗。要使此工作有效盟戏,您必須提供一個(gè)where
子句以限制要?jiǎng)h除的記錄绪妹。
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.運(yùn)行示例:
- 創(chuàng)建一個(gè)新的Flutter項(xiàng)目。
- 將
sqflite
和path
軟件包添加到您的中pubspec.yaml
柿究。 - 將以下代碼粘貼到名為的新文件中
lib/db_test.dart
喂急。 - 使用運(yùn)行代碼
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}';
}
}