Flutter SQLite : Opérations CRUD

-
Étapes pour utiliser SQLite dans Dart’s Flutter
- Résumé
- Voici les étapes requises pour utiliser SQLite dans votre application Flutter.
Étape 1: Importation
sqflite- Vous devez d’abord commencer par importer
sqflitedans votre projet. Ouvrez le fichier et ajoutez la ligne suivante :pubspec.yaml Path_providerpermet de trouver les chemins ou emplacements couramment utilisés sur le système de fichiers.Pathest utile dans les opérations permettant la manipulation de chemins ou d’emplacements.- Ensuite, exécutez
flutter pub getdans le terminal pour installer la dépendance. - Vous pouvez trouver les versions actuelles de ces packages ici :
ou tapez:
flutter pub upgrade --major-versions - Après cela, vous êtes prêt à utiliser
SQLitedans votre applicationFlutter.sqflite
dependencies: flutter: sdk: flutter path_provider: ^2.1.0 path: ^1.6.4 sqflite: ^2.3.0- Vous devez d’abord commencer par importer
Étape 2: Création et ouverture de la base de données
- Ensuite, vous devez créer et ouvrir une base de données à l’aide de la méthode fournie. Par exemple:
openDatabase() - Paramètres de la méthode:
- '
databasesPath' est la variable qui contient le chemin du répertoire où vous souhaitez stocker votre base de données. Vous avez obtenu ce chemin en appelant 'getDatabasesPath()'. - '
getDatabasesPath()' est une fonction asynchrone qui renvoie un 'Future'. Un 'Future' représente une valeur qui sera disponible à un moment donné dans le futur. Dans ce cas, la valeur future est une chaîne de caractères (le chemin du répertoire de la base de données). - En utilisant '
await', vous attendez que le 'Future' retourné par 'getDatabasesPath()' soit résolu, c’est-à-dire que la valeur du chemin soit récupérée avant de continuer l’exécution du reste du code dans la fonction 'createDatabase()'. - La fonction '
join()' est utilisée pour concaténer deux éléments, c’est-à-dire 'databasesPath' et ''my.db'', pour créer un chemin complet vers le fichier de la base de données. Cette fonction est souvent utilisée pour s’assurer que le chemin est correctement formaté selon les conventions du système d’exploitation sur lequel votre application s’exécute. - Enfin, le chemin complet du fichier de base de données ('dbPath') est utilisé pour ouvrir ou créer la base de données SQLite en utilisant la fonction '
openDatabase()'. - L’utilisation de 'await' dans cette situation est importante car elle garantit que le chemin du répertoire de la base de données est récupéré correctement avant d'ouvrir la base de données. Cela évite les erreurs potentielles liées à l’accès au système de fichiers asynchrone.
dbPath: chemin d’accès complet au fichier de base de données SQLite.version: numéro de version de la base de données. Ceci est utilisé pour gérer les modifications de schéma de base de données dans les futures mises à jour d’application.onCreate: fonction de rappel exécutée si la base de données n’existe pas encore (c’est-à-dire qu’elle est créée pour la première fois). Le but de ce rappel est généralement de définir le schéma initial et de remplir la base de données avec des tables et des donnéesinitiales.populateDb
- '
createDatabase() async { String databasesPath = await getDatabasesPath(); String dbPath = join(databasesPath, 'my.db'); var database = await openDatabase(dbPath, version: 1, onCreate: populateDb); return database; }- Ensuite, vous devez créer et ouvrir une base de données à l’aide de la méthode fournie. Par exemple:
Étape 3: Création de la ou des tables de base de données
- Vous devez ensuite définir la fonction que vous avez spécifiée comme rappel :
populateDb() - Dans la fonction de rappel, nous exécutons notre première requête sur la base de données qui nous permet de créer une table appelée avec quatre colonnes. Customer
- Vous pouvez bien sûr créer autant de tables que vous le souhaitez et définir des relations entre elles pour créer le schéma de base de données souhaité. Utiliser Batch
- Dans sqflite, on peut exécuter plusieurs requêtes SQL dans un
batchpour optimiser les performances. Un batch permet d'exécuter plusieurs opérations en une seule transaction, ce qui est plus rapide que de les exécuter une par une. - Un
Batchest un mécanisme qui permet d'exécuter plusieurs requêtes SQL (INSERT, UPDATE, DELETE) en une seule transaction. Cela permet d'améliorer la performance et la fiabilité des opérations sur la base de données. - Comment utiliser un Batch dans sqflite ?
- Dans Flutter, on utilise la méthode
.batch()pour regrouper plusieurs opérations.
1️⃣ Création d'un Batch
- Vous pouvez regrouper plusieurs instructions SQL dans un seul 'Batch', ce qui peut être plus efficace en termes de performances car elles sont exécutées en une seule transaction.
- Toutes les instructions dans le 'Batch' sont exécutées ensemble, et si l’une d’entre elles échoue, toutes les modifications sont annulées (tout ou rien). Cela garantit la cohérence de la base de données.
void populateDb(Database database, int version) async { await database.execute("CREATE TABLE Customer (" "id INTEGER PRIMARY KEY," "first_name TEXT," "last_name TEXT," "email TEXT" ")"); }
2️⃣ Ajout des requêtes dans le BatchBatch batch = db.batch();
3️⃣ Exécution du Batchbatch.insert('table', {'colonne1': 'valeur1', 'colonne2': 'valeur2'}); batch.update('table', {'colonne1': 'nouvelle_valeur'}, where: 'id = ?', whereArgs: [1]); batch.delete('table', where: 'id = ?', whereArgs: [2]);await batch.commit();Si vous souhaitez créer plusieurs tables à la fois, vous devrez appeler database.execute pour chaque instruction de création de table que vous souhaitez exécuter.
void populateDb(Database database, int version) async { // Create the Customer table await database.execute("CREATE TABLE Customer (" "id INTEGER PRIMARY KEY," "first_name TEXT," "last_name TEXT," "email TEXT" ")"); // Create another table (example) await database.execute("CREATE TABLE Order (" "order_id INTEGER PRIMARY KEY," "customer_id INTEGER," "order_date TEXT," "total_amount REAL" ")"); // Create more tables as needed }void populateDb(Database database, int version) async { Batch batch = database.batch(); batch.execute("CREATE TABLE Customer (" "id INTEGER PRIMARY KEY," "first_name TEXT," "last_name TEXT," "email TEXT" ")"); // Vous pouvez ajouter d'autres opérations Batch si nécessaire await batch.commit(); }Si vous souhaitez créer plusieurs tables à la fois.
void populateDb(Database database, int version) async { Batch batch = database.batch(); // Create the Customer table batch.execute("CREATE TABLE Customer (" "id INTEGER PRIMARY KEY," "first_name TEXT," "last_name TEXT," "email TEXT" ")"); // Create another table (example) batch.execute("CREATE TABLE Order (" "order_id INTEGER PRIMARY KEY," "customer_id INTEGER," "order_date TEXT," "total_amount REAL" )"); // Add more table creation statements in the same batch if needed await batch.commit(); }- Vous devez ensuite définir la fonction que vous avez spécifiée comme rappel :
Étape 4: Ajout d'un ou des modèles de données
- Avant de créer les opérations CRUD, nous devons ajouter un modèle. Créez un fichier et ajoutez la classe suivante :lib/model/
customer.dartcomme exemple - Si votre base de données contient plusieurs tables à la fois, vous pouvez créer un modèle pour chaque table ou les mettre dans un seul.
- En règle générale, si votre application est petite à moyenne avec quelques tables, vous pouvez regrouper les modèles dans un seul fichier. Cela simplifie la gestion. Cependant, si votre application est grande et complexe avec de nombreuses tables, il peut être préférable d’utiliser des fichiers séparés pour chaque modèle afin de maintenir une meilleure organisation.
- Dans le fichier déjà crée ajoutez la classe suivante :lib/model/
order.dartcomme exemple
class Customer { int id; String firstName; String lastName; String email; Customer({ this.id, this.firstName, this.lastName, this.email, }); factory Customer.fromMap(Mapmap) { return Customer( id: map['id'], firstName: map['first_name'], lastName: map['last_name'], email: map['email'], ); } } class Order { int orderId; int customerId; String orderDate; double totalAmount; Order({ this.orderId, this.customerId, this.orderDate, this.totalAmount, }); factory Order.fromMap(Map<String, dynamic> map) { return Order( orderId: map['order_id'], customerId: map['customer_id'], orderDate: map['order_date'], totalAmount: map['total_amount'].toDouble(), ); } }- Avant de créer les opérations CRUD, nous devons ajouter un modèle. Créez un fichier et ajoutez la classe suivante :lib/model/
-
Étape 5 : Ajout de méthodes
CRUD- Vous pouvez utiliser différentes approches pour exécuter des opérations CRUD : les RawSQLrequêtes ou une API de haut niveau.
-
Étape 5.1 : Implémentation de l'opération
Create- Vous pouvez utiliser différentes approches pour exécuter des opérations
CRUD: les requêtes ou une API de haut niveau.RawSQL - Commençons par une méthode pour créer un customer dans la table de base de données :
- Première approche : utiliser la méthode
insert()- Comme vous pouvez le voir, nous convertissons simplement notre objet customer en map (en utilisant la méthode que nous avons définie dans le modèle) et nous le passons à la méthode qui prend le nom de la table comme premier paramètre et les données comme second paramètre.
toMap()Customerinsert()
Future<int> createCustomer(Customer customer) async { var result = await database.insert("Customer", customer.toMap()); return result; } - Comme vous pouvez le voir, nous convertissons simplement notre objet customer en map (en utilisant la méthode que nous avons définie dans le modèle) et nous le passons à la méthode qui prend le nom de la table comme premier paramètre et les données comme second paramètre.
- Deuxième approche : utiliser la méthode
rawInsert()- La méthode
rawInsert()est une méthodesqflitepour Flutter, qui permet d’insérer des données directement sous forme de requête SQL brute dans une base de données.
createCustomer(Customer customer) async { var result = await database.rawInsert( "INSERT INTO Customer (id,first_name, last_name, email)" " VALUES (${customer.id},${customer.firstName},${customer.lastName},${customer.email})"); return result; } - La méthode
- Vous pouvez utiliser différentes approches pour exécuter des opérations
Étape 5.2 : Implémentation de l'opération
Read (All)- Maintenant, implémentons l'opération de lecture de CRUD,
- Première approche: utiliser la méthode
query()- La méthode
query()est une abstraction de haut niveau qui prend le nom de la table et les colonnes renvoient ensuite des données. - Nous utilisons la méthode
Listpour convertir le jeu de résultats en Flutter.toList()
Future<List> getCustomers() async { var result = await database.query("Customer", columns: ["id", "first_name", "last_name", "email"]); return result.toList(); } - La méthode
- Deuxième approche : utiliser la méthode
rawQuery()- La méthode '
rawQuery sqflitepour Flutter, qui permet d’exécuter des requêtes SQL brutes dans une base de données et de récupérer les résultats sous forme de liste de résultats (généralement une liste de maps). - Avec la méthode, il vous suffit de passer la requête
SELECT brute.rawQuery()
Future<List> getCustomers() async { var result = await database.rawQuery('SELECT * FROM Customer'); return result.toList(); } - La méthode '
Étape 5.3 :Implémentation de l’opération
Read(by Id)- Après avoir obtenu tous les customer de la base de données, nous devons maintenant obtenir un seul customer par son identifiant.
- Première approche : utiliser la méthode
query()- Tout comme l’exemple précédent, nous utilisons la méthode de requête pour obtenir des données à partir d’une table.
- Nous spécifions la table comme premier paramètre, les colonnes comme deuxième paramètre et cette fois nous ajoutons également un paramètre Where qui prend la clause WHERE et un tableau WhereArgs pour passer les arguments Where.
- Nous voulons obtenir un client par
id = ?donc nous passons une clause. Le symbole sera?remplacé par la valeur réelle du paramètrewhereArgs
Future<Customer> getCustomer(int id) async { List<Map> results = await db.query("Customer", columns: ["id", "first_name", "last_name", "email"], where: 'id = ?', whereArgs: [id]); if (results.length > 0) { return new Customer.fromMap(results.first); } return null; } - Deuxième approche : utiliser la méthode
rawQuery()Future<Customer> getCustomer(int id) async { var results = await database.rawQuery('SELECT * FROM Customer WHERE id = $id'); if (results.length > 0) { return new Customer.fromMap(results.first); } return null; }
Étape 5.4 :Implémentation de l’opération de mise à jour
(Update)- Maintenant, implémentons l’opération de mise à jour en utilisant les deux approches.
- Première approche: utiliser la méthode
update()- La méthode est similaire à la méthode, mais pour la mise à jour des données :update()query()
- Nous transmettons le nom de la table, les données client sous forme de carte, la clause
WHEREet les argumentsWHERE.
Future<int> updateCustomer(Customer customer) async { return await database.update("Customer", customer.toMap(), where: "id = ?", whereArgs: [customer.id]); } - Deuxième approche; Utilisation de la méthode
rawUpdate()- La méthode
rawUpdate()est utilisée pour exécuter une requête UPDATE brute sur la base de données :
Future<iint> updateCustomer(Customer customer) async { return await database.rawUpdate( 'UPDATE Customer SET first_name = ${customer.firstName} WHERE id = ${customer.id}' ); } - La méthode
Étape 5.5 :Implémentation de l’opération de suppression
(Delete)- Enfin, nous devons implémenter l'opération de suppression de notre exemple CRUD. Cela peut également être fait en suivant deux approches :
- Première approche : utilisation de la méthode
delete()- La méthode
delete()prend un nom de table, la clauseWHEREet les arguments WHERE :
Future<int> deleteCustomer(int id) async { return await database.delete("Customer", where: 'id = ?', whereArgs: [id]); } - La méthode
- Deuxième approche; Utilisation de la méthode
rawDelete()- La méthode
rawDelete()prend une requêteDELETEbrute :
Future<int> deleteCustomer(int id) async { return await db.rawDelete('DELETE FROM Customer WHERE id = $id'); } - La méthode
Étape 06: Fermer la base de données
- Une fois la base de données terminée, vous pouvez exécuter la méthode suivante pour la fermer:
await database.close();