Floor — wat is het, ORM bovenop SQLite in Flutter

Auteur: IT Sectr Gepubliceerd: 2026-03-13 Leestijd: 9 min

Floor — ORM (Object-Relational Mapping) voor Flutter, die een getypeerde laag bovenop SQLite biedt. In tegenstelling tot raw SQLite-query's genereert Floor DAO-klassen uit geannoteerde Dart-modellen. Volgens Pub.dev, 2024 wordt Floor gebruikt in meer dan 3500 Flutter-projecten en behoort het tot de top drie van populairste ORM-oplossingen voor lokale gegevensopslag, naast drift en hive.

Belangrijkste punten

  • Floor — ORM bovenop SQLite met codegeneratie van DAO en Entity via annotaties
  • Typeveiligheid — query's worden gecontroleerd tijdens compilatie, waardoor runtime SQL-fouten worden geëlimineerd
  • DAO-patroon — Data Access Object encapsuleert SQL-query's in Dart-methoden
  • Migraties — ingebouwde ondersteuning voor versiebeheer van SQLite-schema
  • Reactiviteit — Flow-query's via Stream voor automatische UI-updates

Wat is Floor?

Floor — is een ORM-bibliotheek voor Flutter en Dart, gebouwd op basis van SQLite. Het gebruikt annotaties om entiteiten (Entity), Data Access Object (DAO) en database (Database) te beschrijven. Codegeneratie gebeurt via build_runner en floor_generator — de compiler maakt DAO-implementaties en de beherende databaseklasse. In tegenstelling tot raw sqflite elimineert Floor volledig de noodzaak om handmatig ResultSet naar Dart-objecten te converteren, door automatisch kolommen naar Entity-velden te mappen via typereflectie.

Floor volgt het Repository + DAO-patroon, bekend bij Android-ontwikkelaars uit Room. Elke tabel wordt vertegenwoordigd door een Dart-klasse met de annotatie @Entity, SQL-query's worden gegroepeerd in interfaces met de annotatie @dao, en de database wordt samengesteld in een abstracte klasse met @Database. Deze aanpak scheidt het datamodel strikt van de querylogica.

Volgens Flutter Pulse (2023) wordt Floor gekozen in 28% van de Flutter-projecten die een lokale database vereisen. De belangrijkste redenen voor de keuze — bekendheid met SQL (geen nieuwe querytaal leren) en controle van query's tijdens compilatie. Bovendien genereert Floor leesbare code die gemakkelijk te debuggen is in tegenstelling tot meer abstracte ORM's met aangepaste DSL, wat de drempel voor nieuwe ontwikkelaars in het team verlaagt.

Floor architectuur

Floor bestaat uit drie lagen: Entity (tabelmodel), DAO (query-interface) en Database (ingangspunt). De generator maakt implementaties _$_Entity voor veldmapping en _$_Dao voor SQL-uitvoering. Bij wijziging van Entity of DAO is het voldoende om build_runner opnieuw te starten — de code wordt automatisch bijgewerkt. Voor migratie tussen schemaversies gebruikt Floor sequentiële versienummers, wat gegevensintegriteit garandeert bij het bijwerken van de app op gebruikersapparaten.

Hoe werkt Floor in Flutter?

Floor gebruikt SQLite via het pakket sqflite voor platformbuilds en sqlite3 voor desktop en web. Bij het starten van de app maakt of opent Floor het SQLite-bestand, past migraties toe en bereidt DAO-methoden voor op het uitvoeren van query's. Alle bewerkingen worden asynchroon uitgevoerd via Future en Stream.

Codegeneratie in Floor werkt volgens het volgende principe: de parser leest annotaties uit de broncode, maakt een AST (Abstract Syntax Tree) van modellen en query's, en genereert vervolgens Dart-bestanden met het voorvoegsel _$. De gegenereerde code bevat mappers voor ResultSet → Entity en omgekeerd.

Draadveiligheid

Floor werkt met SQLite in één isolaat. Alle query's worden asynchroon uitgevoerd, maar gelijktijdige schrijfbewerkingen worden geblokkeerd op SQLite-niveau. Voor transacties wordt de annotatie @transaction gebruikt, die de atomiciteit van een groep query's en terugdraaien bij fouten garandeert.

Floor vs Drift: ORM-vergelijking voor Flutter

Zowel Floor als Drift — zijn ORM's bovenop SQLite, maar ze verschillen in filosofie. Floor staat dichter bij Room uit Android, Drift — is reactiever met ingebouwde Stream API en querycompilatie via SQL-bestanden. De keuze tussen hen hangt af van de ervaring van het team en de vereiste reactiviteit.

KenmerkFloorDrift
QuerytypeSQL-strings in @QueryDart-methoden + sql-bestanden
Codegeneratiefloor_generator (build_runner)drift_dev (build_runner)
ReactiviteitStream uit DAOIngebouwde Stream API + auto-updating
ComplexiteitLaag (bekende SQL)Middel (eigen DSL)
MigratiesHandmatige SQL-scriptsAutomatisch + handmatig
CompatibiliteitAndroid, iOS, macOSAndroid, iOS, Web, macOS, Linux

Wanneer Floor kiezen

Floor — de keuze voor teams die al bekend zijn met SQL en Android Room. Als ontwikkelaars gewend zijn SQL-query's handmatig te schrijven en een minimale laag bovenop SQLite willen — biedt Floor typering zonder een nieuwe DSL te leren. Het is ook gemakkelijker te debuggen omdat de gegenereerde code leesbaar en voorspelbaar is.

Wanneer Drift beter is

Drift biedt krachtigere reactiviteit en ondersteunt meer platforms. Als de app actief Stream gebruikt voor UI-updates, complexe query's met JOIN en subquery's vereist, of voor web wordt gebouwd — heeft Drift de voorkeur. De instapdrempel is echter hoger vanwege de noodzaak om de eigen DSL te leren.

Codevoorbeelden met Floor

Floor is gebouwd rond annotaties. Hieronder staat een volledig voorbeeld van Entity, DAO en Database voor een takenlijst-app. Na het uitvoeren van build_runner zijn de gegenereerde klassen klaar voor gebruik.

Definitie van Entity en DAO

De klasse TaskEntity met de annotatie @Entity wordt naar de tabel task gemapt. Het veld met @primaryKey wordt de primaire sleutel. De interface TaskDao bevat methoden voor bewerkingen op de tabel — elke methode is geannoteerd met @Query, @Insert, @Update of @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);
}

Database-initialisatie

De abstracte klasse met de annotatie @Database verbindt Entity en DAO. De methode databaseBuilder maakt een database-instantie. Na het aanroepen van build is de database klaar: Floor opent het SQLite-bestand, past migraties toe en retourneert DAO voor gebruik.

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

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

Reactieve query's via Stream

Floor ondersteunt het retourneren van Stream uit DAO-methoden. Bij elke wijziging in de tabel zendt Stream een nieuwe lijst uit. Dit integreert met StreamBuilder in Flutter — de UI wordt automatisch bijgewerkt bij het toevoegen, wijzigen of verwijderen van records.

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

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

Migraties en versiebeheer in Floor

Floor ondersteunt versiebeheer van de database via de parameter version in de annotatie @Database. Bij wijziging van Entity (toevoegen of verwijderen van velden) moet u de versie verhogen en een migratie toevoegen. Een migratie is een Dart-functie die een transactie ontvangt en SQL-query's ALTER TABLE uitvoert.

Migratievoorbeeld

Stel dat we in versie 2 het veld dueDate aan TaskEntity hebben toegevoegd. De migratie wordt uitgevoerd met de SQL-query ALTER TABLE. Als er geen migratie is opgegeven, roept Floor MigrationStrategy aan, waar een fallback kan worden ingesteld (bijvoorbeeld het opnieuw aanmaken van de tabel met gegevensverlies).

Testen van Floor-query's

Floor biedt geen ingebouwd mock-framework, maar de database kan eenvoudig worden vervangen in tests. Maak inMemoryDatabaseBuilder — het maakt een SQLite-database in het geheugen, qua schema identiek aan de productie. Na elke test wist u de gegevens via deleteDatabase voor isolatie van testscenario's.

Transacties en batchbewerkingen in Floor

Floor ondersteunt transacties via de annotatie @transaction op de DAO-methode. Binnen een transactie worden meerdere query's sequentieel uitgevoerd met terugdraaigarantie bij fouten. Batch-invoeging via @Insert met de parameter List<T> optimaliseert het invoegen van meerdere records in één aanroep — dit is meerdere keren sneller dan het afzonderlijk invoegen in een lus. Gebruik voor massale bewerkingen batch-invoeging van 100–200 records: dit is de optimale balans tussen uitvoeringssnelheid en RAM-verbruik op mobiele apparaten met beperkte middelen.

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();

Veelgestelde vragen

Waarin verschilt Floor van raw sqflite?

sqflite vereist het handmatig schrijven van SQL-query's en het mappen van ResultSet naar objecten. Floor genereert deze code automatisch: u beschrijft Entity en DAO, en getypeerde methoden retourneren kant-en-klare Dart-objecten. Floor controleert ook SQL-query's tijdens compilatie via annotaties.

Ondersteunt Floor relaties tussen tabellen?

Floor heeft geen ingebouwde annotaties voor relaties (ForeignKey, @Relation), zoals Room. Relaties worden geïmplementeerd via handmatige SQL JOIN-query's in @Query. Voor complexe relationele schema's kunt u beter Drift overwegen met zijn ingebouwde ondersteuning voor relaties.

Hoe debug ik Floor SQL-query's?

Floor maakt het mogelijk om de callback callback in te schakelen bij het maken van DatabaseBuilder — hieraan wordt een instantie van sqflite.Database doorgegeven waar een logger aan kan worden gekoppeld. Gebruik alternatief floor_doctor voor visualisatie van het schema en gegevens in de ontwikkelmodus.

Kan Floor worden gebruikt voor web-builds?

Floor gebruikt sqflite, dat niet werkt in een webomgeving. Voor web is een aparte build met sqlite3 via WASM nodig. In de huidige versie ondersteunt Floor officieel Android, iOS en macOS. Gebruik voor web Drift met de sqlite3-adapter.

Hoe werkt querycaching in Floor?

Floor heeft geen ingebouwde caching — elke query wordt uitgevoerd naar SQLite. Gebruik voor het cachen van herhaalde query's een Repository-laag met in-memory cache (bijvoorbeeld dart_cache). Floor genereert alleen code voor het werken met SQLite, zonder er extra lagen bovenop toe te voegen.

Samenvatting

  • Floor — ORM bovenop SQLite met codegeneratie van Entity, DAO en Database via annotaties
  • Typeveiligheid — SQL-query's worden gecontroleerd tijdens compilatie via de annotatie @Query
  • DAO-patroon — SQL-query's geëncapsuleerd in Dart-methoden, model en logica scheidend
  • Migraties — schemaversiebeheer via Migration met handmatige ALTER TABLE
  • Reactiviteit — Stream uit DAO voor automatische UI-updates bij wijzigingen
  • Beperkingen — geen ingebouwde relaties, geen ondersteuning voor web-builds
  • Aanbeveling — kies Floor voor Flutter-projecten waar het team bekend is met SQL en de Room-aanpak

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook