Floor — qu’est-ce que c’est, ORM sur SQLite dans Flutter

Auteur : IT Sectr Publié le : 2026-03-13 Temps de lecture : 9 min

Floor — ORM (Object-Relational Mapping) pour Flutter, fournissant une couche typée au-dessus de SQLite. Contrairement aux requêtes SQLite brutes, Floor génère des classes DAO à partir de modèles Dart annotés. Selon Pub.dev, 2024, Floor est utilisé dans plus de 3500 projets Flutter et fait partie des trois solutions ORM les plus populaires pour le stockage local de données avec drift et hive.

Points Clés

  • Floor — ORM sur SQLite avec génération de code DAO et Entity via annotations
  • Sécurité de type — les requêtes sont vérifiées à la compilation, éliminant les erreurs SQL d’exécution
  • Patron DAO — Data Access Object encapsule les requêtes SQL dans des méthodes Dart
  • Migrations — prise en charge intégrée du versionnage de schéma SQLite
  • Réactivité — requêtes Flow via Stream pour la mise à jour automatique de l’UI

Qu’est-ce que Floor ?

Floor est une bibliothèque ORM pour Flutter et Dart construite sur SQLite. Elle utilise des annotations pour décrire les entités (Entity), les Data Access Objects (DAO) et la base de données (Database). La génération de code est effectuée via build_runner et floor_generator — le compilateur crée des implémentations DAO et une classe de gestion de base de données. Contrairement à sqflite brut, Floor élimine complètement le besoin de conversion manuelle de ResultSet en objets Dart en mappant automatiquement les colonnes vers les champs Entity par réflexion de types.

Floor suit le patron Repository + DAO familier aux développeurs Android avec Room. Chaque table est représentée par une classe Dart avec l’annotation @Entity, les requêtes SQL sont regroupées dans des interfaces avec l’annotation @dao, et la base de données est assemblée dans une classe abstraite avec @Database. Cette approche sépare strictement le modèle de données de la logique de requêtes.

Selon Flutter Pulse (2023), Floor est choisi dans 28 % des projets Flutter nécessitant une base de données locale. Les principales raisons de ce choix sont la familiarité avec SQL (pas besoin d’apprendre un nouveau langage de requêtes) et la vérification des requêtes à la compilation. De plus, Floor génère un code lisible facile à déboguer par rapport aux ORM plus abstraits avec DSL personnalisés, ce qui abaisse la barrière à l’entrée pour les nouveaux développeurs dans l’équipe.

Architecture de Floor

Floor se compose de trois couches : Entity (modèle de table), DAO (interface de requêtes) et Database (point d’entrée). Le générateur crée des implémentations _$_Entity pour le mappage de champs et _$_Dao pour l’exécution SQL. Lorsque Entity ou DAO change, il suffit de redémarrer build_runner — le code se met à jour automatiquement. Pour la migration entre versions de schéma, Floor utilise des numéros de version séquentiels, garantissant l’intégrité des données lors de la mise à jour de l’application sur les appareils des utilisateurs.

Comment Floor fonctionne-t-il dans Flutter ?

Floor utilise SQLite via le paquet sqflite pour les builds natifs et sqlite3 pour le bureau et le web. Au démarrage de l’application, Floor crée ou ouvre le fichier SQLite, applique les migrations et prépare les méthodes DAO pour exécuter les requêtes. Toutes les opérations sont effectuées de manière asynchrone via Future et Stream.

La génération de code dans Floor fonctionne comme suit : l’analyseur lit les annotations des fichiers source, crée un AST (Arbre Syntaxique Abstrait) des modèles et requêtes, puis génère des fichiers Dart avec le préfixe _$. Le code généré inclut les mappeurs ResultSet → Entity et vice versa.

Sécurité des threads

Floor travaille avec SQLite dans un seul isolate. Toutes les requêtes sont exécutées de manière asynchrone, mais les écritures concurrentes sont verrouillées au niveau SQLite. Pour les transactions, l’annotation @transaction est utilisée, garantissant l’atomicité d’un groupe de requêtes et le rollback en cas d’erreur.

Floor vs Drift : comparaison d’ORM pour Flutter

Floor et Drift sont tous deux des ORM sur SQLite, mais ils diffèrent par leur philosophie. Floor est plus proche de Room d’Android, Drift est plus réactif avec une API Stream intégrée et une compilation de requêtes via des fichiers SQL. Le choix entre eux dépend de l’expérience de l’équipe et de la réactivité requise.

CaractéristiqueFloorDrift
Type de requêtesChaînes SQL dans @QueryMéthodes Dart + fichiers sql
Génération de codefloor_generator (build_runner)drift_dev (build_runner)
RéactivitéStream depuis DAOAPI Stream intégrée + mise à jour automatique
ComplexitéFaible (SQL familier)Moyenne (DSL propre)
MigrationsScripts SQL manuelsAutomatiques + manuelles
CompatibilitéAndroid, iOS, macOSAndroid, iOS, Web, macOS, Linux

Quand choisir Floor

Floor est le choix pour les équipes déjà familières avec SQL et Android Room. Si les développeurs ont l’habitude d’écrire des requêtes SQL manuellement et souhaitent une enveloppe minimale sur SQLite — Floor offre le typage sans apprendre un nouveau DSL. Il est également plus facile à déboguer car le code généré est lisible et prévisible.

Quand Drift est meilleur

Drift offre une réactivité plus puissante et supporte davantage de plateformes. Si l’application utilise activement Stream pour mettre à jour l’UI, nécessite des requêtes complexes avec JOIN et sous-requêtes ou cible le web — Drift est préférable. Cependant, sa barrière à l’entrée est plus élevée en raison de la nécessité d’apprendre son propre DSL.

Exemples de code avec Floor

Floor est construit autour d’annotations. Vous trouverez ci-dessous un exemple complet d’Entity, DAO et Database pour une application de liste de tâches. Après avoir exécuté build_runner, les classes générées sont prêtes à l’emploi.

Définition d’Entity et DAO

La classe TaskEntity avec l’annotation @Entity est mappée sur la table task. Un champ avec @primaryKey devient la clé primaire. L’interface TaskDao contient des méthodes pour les opérations sur la table — chaque méthode est annotée avec @Query, @Insert, @Update ou @Delete.

dart
@entity
class TaskEntity {
    @PrimaryKey(autoGenerate: true)
    final int id;
    final String title;
    final bool isCompleted;
    final int priority;

    TaskEntity({this.id, required this.title,
        this.isCompleted = false, this.priority = 0});
}

@dao
abstract class TaskDao {
    @Query('SELECT * FROM TaskEntity ORDER BY priority DESC')
    Future<List<TaskEntity>> getAllTasks();

    @Insert
    Future<int> insertTask(TaskEntity task);

    @Update
    Future<void> updateTask(TaskEntity task);

    @Query('SELECT * FROM TaskEntity WHERE isCompleted = :status')
    Stream<List<TaskEntity>> watchTasks(bool status);
}

Initialisation de la base de données

Une classe abstraite avec l’annotation @Database lie Entity et DAO. La méthode databaseBuilder crée une instance de base de données. Après avoir appelé build, la base de données est prête : Floor ouvre le fichier SQLite, applique les migrations et retourne le DAO pour le travail.

dart
@Database(version: 1, entities: [TaskEntity])
abstract class AppDatabase extends FloorDatabase {
    TaskDao get taskDao;
}

// Utilisation
final database = await $FloorAppDatabase.databaseBuilder('app.db').build();
final taskDao = database.taskDao;
final tasks = await taskDao.getAllTasks();

Requêtes réactives via Stream

Floor prend en charge le retour de Stream depuis les méthodes DAO. Lors de toute modification dans la table, le Stream émet une nouvelle liste. Cela s’intègre avec StreamBuilder dans Flutter — l’UI se met automatiquement à jour lors de l’ajout, la modification ou la suppression d’enregistrements.

dart
@Query('SELECT * FROM TaskEntity ORDER BY priority DESC')
Stream<List<TaskEntity>> watchAllTasks();

// Dans le widget Flutter
StreamBuilder<List<TaskEntity>>(
    stream: taskDao.watchAllTasks(),
    builder: (context, snapshot) {
        final tasks = snapshot.data ?? [];
        return ListView.builder(
            itemCount: tasks.length,
            itemBuilder: (_, i) => TaskTile(tasks[i]),
        );
    },
)

Migrations et versionnage dans Floor

Floor prend en charge le versionnage de base de données via le paramètre version dans l’annotation @Database. Lorsque Entity change (ajout ou suppression de champs), vous devez incrémenter la version et ajouter une migration. Une migration est une fonction Dart qui reçoit une transaction et exécute des requêtes SQL ALTER TABLE.

Exemple de migration

Supposons qu’à la version 2 nous ayons ajouté un champ dueDate à TaskEntity. La migration est effectuée via une requête SQL ALTER TABLE. Si une migration n’est pas spécifiée, Floor appelle MigrationStrategy où vous pouvez définir un fallback (par exemple, recréer la table avec perte de données).

Tester les requêtes Floor

Floor ne fournit pas de framework mock intégré, mais la base de données peut facilement être remplacée dans les tests. Créez un inMemoryDatabaseBuilder — il crée une base de données SQLite en mémoire identique en schéma à la production. Après chaque test, nettoyez les données via deleteDatabase pour isoler les scénarios de test.

Transactions et opérations par lots dans Floor

Floor prend en charge les transactions via l’annotation @transaction sur les méthodes DAO. À l’intérieur d’une transaction, plusieurs requêtes sont exécutées séquentiellement avec garantie de rollback en cas d’erreur. L’insertion par lots via @Insert avec un paramètre List optimise l’insertion de plusieurs enregistrements en un seul appel — c’est plusieurs fois plus rapide que d’insérer un enregistrement à la fois dans une boucle. Pour les opérations en masse, utilisez des insertions par lots de 100 à 200 enregistrements : c’est l’équilibre optimal entre vitesse d’exécution et consommation de RAM sur les appareils mobiles aux ressources limitées.

dart
final migration1to2 = Migration(1, 2, (database) async {
    await database.execute(
        'ALTER TABLE TaskEntity ADD COLUMN dueDate TEXT'
    );
});

final database = await $FloorAppDatabase.databaseBuilder('app.db')
    .addMigrations([migration1to2])
    .build();

Foire Aux Questions

En quoi Floor est-il différent de sqflite brut ?

sqflite nécessite l’écriture manuelle de requêtes SQL et le mappage de ResultSet vers des objets. Floor génère ce code automatiquement : vous décrivez Entity et DAO, et les méthodes typées retournent des objets Dart prêts à l’emploi. Floor vérifie également les requêtes SQL à la compilation via les annotations.

Floor prend-il en charge les relations entre tables ?

Floor ne dispose pas d’annotations intégrées pour les relations (ForeignKey, @Relation) comme Room. Les relations sont implémentées via des requêtes SQL JOIN manuelles dans @Query. Pour les schémas relationnels complexes, envisagez Drift avec sa prise en charge intégrée des relations.

Comment déboguer les requêtes SQL Floor ?

Floor permet d’activer un callback lors de la création de DatabaseBuilder — il reçoit une instance de sqflite.Database sur laquelle vous pouvez attacher un logger. Alternativement, utilisez floor_doctor pour visualiser le schéma et les données en mode dev.

Peut-on utiliser Floor pour les builds web ?

Floor utilise sqflite, qui ne fonctionne pas dans un environnement web. Pour le web, un build séparé avec sqlite3 via WASM est nécessaire. Dans la version actuelle, Floor supporte officiellement Android, iOS et macOS. Pour le web, utilisez Drift avec l’adaptateur sqlite3.

Comment fonctionne la mise en cache des requêtes dans Floor ?

Floor n’a pas de cache intégré — chaque requête est exécutée sur SQLite. Pour mettre en cache les requêtes répétées, utilisez une couche Repository avec cache en mémoire (par exemple, dart_cache). Floor génère uniquement le code pour travailler avec SQLite sans ajouter de surcharge.

Résumé

  • Floor — ORM sur SQLite avec génération de code Entity, DAO et Database via annotations
  • Sécurité de type — les requêtes SQL sont vérifiées à la compilation via l’annotation @Query
  • Patron DAO — les requêtes SQL sont encapsulées dans des méthodes Dart, séparant le modèle de la logique
  • Migrations — versionnage de schéma via Migration avec ALTER TABLE manuel
  • Réactivité — Stream depuis DAO pour mise à jour automatique de l’UI lors des modifications
  • Limitations — pas de relations intégrées, ne supporte pas les builds web
  • Recommandation — choisissez Floor pour les projets Flutter où l’équipe connaît SQL et l’approche Room

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi