Skip to content

SQLite Flutter avec sqflite

Pour des données plus complexes et des relations entre entités, SQLite est la solution recommandée.

dependencies:
sqflite: ^2.3.0
path: ^1.8.3
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static final DatabaseHelper _instance = DatabaseHelper._internal();
factory DatabaseHelper() => _instance;
DatabaseHelper._internal();
Database? _database;
Future<Database> get database async {
_database ??= await _initDatabase();
return _database!;
}
Future<Database> _initDatabase() async {
String path = join(await getDatabasesPath(), 'app_database.db');
return await openDatabase(
path,
version: 1,
onCreate: _onCreate,
);
}
Future<void> _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE users(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at TEXT NOT NULL
)
''');
await db.execute('''
CREATE TABLE tasks(
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
description TEXT,
completed INTEGER NOT NULL DEFAULT 0,
user_id INTEGER,
FOREIGN KEY (user_id) REFERENCES users (id)
)
''');
}
}
class User {
final int? id;
final String name;
final String email;
final DateTime createdAt;
User({this.id, required this.name, required this.email, required this.createdAt});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'email': email,
'created_at': createdAt.toIso8601String(),
};
}
factory User.fromMap(Map<String, dynamic> map) {
return User(
id: map['id'],
name: map['name'],
email: map['email'],
createdAt: DateTime.parse(map['created_at']),
);
}
}
class UserRepository {
final DatabaseHelper _dbHelper = DatabaseHelper();
Future<int> insertUser(User user) async {
final db = await _dbHelper.database;
return await db.insert('users', user.toMap());
}
Future<List<User>> getAllUsers() async {
final db = await _dbHelper.database;
final List<Map<String, dynamic>> maps = await db.query('users');
return List.generate(maps.length, (i) => User.fromMap(maps[i]));
}
Future<User?> getUserById(int id) async {
final db = await _dbHelper.database;
final List<Map<String, dynamic>> maps = await db.query(
'users',
where: 'id = ?',
whereArgs: [id],
);
if (maps.isNotEmpty) {
return User.fromMap(maps.first);
}
return null;
}
Future<int> updateUser(User user) async {
final db = await _dbHelper.database;
return await db.update(
'users',
user.toMap(),
where: 'id = ?',
whereArgs: [user.id],
);
}
Future<int> deleteUser(int id) async {
final db = await _dbHelper.database;
return await db.delete(
'users',
where: 'id = ?',
whereArgs: [id],
);
}
}
Future<void> transferTasks(int fromUserId, int toUserId) async {
final db = await DatabaseHelper().database;
await db.transaction((txn) async {
// Vérifier que les utilisateurs existent
final fromUser = await txn.query('users', where: 'id = ?', whereArgs: [fromUserId]);
final toUser = await txn.query('users', where: 'id = ?', whereArgs: [toUserId]);
if (fromUser.isEmpty || toUser.isEmpty) {
throw Exception('Utilisateur non trouvé');
}
// Transférer les tâches
await txn.update(
'tasks',
{'user_id': toUserId},
where: 'user_id = ?',
whereArgs: [fromUserId],
);
});
}
class DatabaseHelper {
Future<Database> _initDatabase() async {
return await openDatabase(
path,
version: 2, // Version mise à jour
onCreate: _onCreate,
onUpgrade: _onUpgrade,
);
}
Future<void> _onUpgrade(Database db, int oldVersion, int newVersion) async {
if (oldVersion < 2) {
await db.execute('ALTER TABLE users ADD COLUMN avatar_url TEXT');
}
}
}
  1. Singleton Pattern : Utiliser une seule instance de DatabaseHelper
  2. Transactions : Grouper les opérations liées pour maintenir la cohérence
  3. Index : Créer des index sur les colonnes fréquemment interrogées
  4. Migrations : Planifier et tester les changements de schéma
  5. Gestion d’erreurs : Toujours gérer les exceptions SQLite
  6. Fermeture : Fermer la base de données quand nécessaire
  7. Tests : Écrire des tests unitaires pour toutes les opérations
  • Applications CRUD : Gestion d’utilisateurs, tâches, notes
  • Données relationnelles : Relations entre entités
  • Requêtes complexes : Jointures, agrégations, filtres avancés
  • Intégrité référentielle : Contraintes de clés étrangères
  • Cache local : Stockage de données synchronisées avec serveur