Floor — mi ez, ORM az SQLite fölött Flutterben

Szerző: IT Sectr Megjelenés: 2026-03-13 Olvasási idő: 9 perc

Floor — ORM (Object-Relational Mapping) Flutterhez, amely tipizált réteget biztosít az SQLite fölött. Ellentétben a nyers SQLite lekérdezésekkel, a Floor DAO osztályokat generál annotált Dart modellekből. A Pub.dev, 2024 adatai szerint a Floor-t több mint 3500 Flutter projektben használják, és a három legnépszerűbb ORM megoldás közé tartozik a helyi adattároláshoz a drift és a hive mellett.

Főbb pontok

  • Floor — ORM az SQLite fölött DAO és Entity kódgenerálással annotációkon keresztül
  • Típusbiztonság — a lekérdezések fordítási időben ellenőrizve, kiküszöbölve a futásidejű SQL hibákat
  • DAO minta — Data Access Object az SQL lekérdezéseket Dart metódusokba kapszulázza
  • Migrációk — beépített támogatás az SQLite séma verziókezeléséhez
  • Reaktivitás — Flow lekérdezések Stream-en keresztül az UI automatikus frissítéséhez

Mi az a Floor?

Floor — egy ORM könyvtár Flutter és Dart számára, az SQLite alapjaira építve. Annotációkat használ entitások (Entity), Data Access Object (DAO) és adatbázis (Database) leírásához. A kódgenerálás a build_runner és floor_generator segítségével történik — a fordító létrehozza a DAO implementációkat és az adatbázis-kezelő osztályt. Ellentétben a nyers sqflite-tal, a Floor teljesen kiküszöböli a ResultSet manuális Dart objektumokká alakításának szükségességét, automatikusan leképezve az oszlopokat az Entity mezőire típusreflexió segítségével.

A Floor a Repository + DAO mintát követi, amely ismerős az Android fejlesztők számára a Room-ból. Minden táblát egy Dart osztály képvisel a @Entity annotációval, az SQL lekérdezések a @dao annotációval ellátott interfészekbe vannak csoportosítva, és az adatbázis egy @Database annotációval ellátott absztrakt osztályban van összeállítva. Ez a megközelítés szigorúan elválasztja az adatmodellt és a lekérdezési logikát.

A Flutter Pulse (2023) szerint a Floor-t a Flutter projektek 28%-ában választják, ahol helyi adatbázisra van szükség. A választás fő okai — az SQL ismerete (nem kell új lekérdezési nyelvet tanulni) és a lekérdezések fordítási időben történő ellenőrzése. Ezenkívül a Floor olvasható kódot generál, amely könnyen debugolható, ellentétben az elvontabb, egyedi DSL-lel rendelkező ORM-ekkel, ami csökkenti a belépési küszöböt az új fejlesztők számára a csapatban.

A Floor architektúrája

Floor három rétegből áll: Entity (táblamodell), DAO (lekérdezési interfész) és Database (belépési pont). A generátor létrehozza a _$_Entity implementációkat a mezők leképezéséhez és a _$_Dao implementációkat az SQL végrehajtásához. Az Entity vagy DAO megváltoztatásakor elegendő újraindítani a build_runner-t — a kód automatikusan frissül. A séma verziói közötti migrációhoz a Floor szekvenciális verziószámokat használ, ami garantálja az adatok integritását az alkalmazás frissítésekor a felhasználók eszközein.

Hogyan működik a Floor Flutterben?

Floor az SQLite-ot használja a sqflite csomagon keresztül platform build-ekhez és a sqlite3-at asztali és webes környezethez. Az alkalmazás indításakor a Floor létrehozza vagy megnyitja az SQLite fájlt, alkalmazza a migrációkat és előkészíti a DAO metódusokat a lekérdezések végrehajtásához. Minden művelet aszinkron módon történik a Future és Stream segítségével.

A kódgenerálás a Floor-ban a következő elv szerint működik: az elemző beolvassa az annotációkat a forráskódból, létrehozza a modellek és lekérdezések AST (Abstract Syntax Tree) fáját, majd _$ előtaggal ellátott Dart fájlokat generál. A generált kód tartalmazza a ResultSet → Entity és visszirányú leképezőket.

Szálbiztonság

Floor egy izolátumban dolgozik az SQLite-tal. Minden lekérdezés aszinkron módon hajtódik végre, de a párhuzamos írások blokkolva vannak az SQLite szintjén. Tranzakciókhoz a @transaction annotációt használják, amely garantálja a lekérdezési csoport atomitását és visszagörgetést hiba esetén.

Floor vs Drift: ORM összehasonlítás Flutterhez

Mind a Floor, mind a Drift — ORM az SQLite fölött, de filozófiájukban különböznek. A Floor közelebb áll az Android-beli Room-hoz, a Drift — reaktívabb a beépített Stream API-val és a lekérdezések SQL fájlokon keresztüli fordításával. A köztük lévő választás a csapat tapasztalatától és a szükséges reaktivitástól függ.

JellemzőFloorDrift
Lekérdezés típusaSQL sztringek a @Query-benDart metódusok + sql fájlok
Kódgenerálásfloor_generator (build_runner)drift_dev (build_runner)
ReaktivitásStream a DAO-bólBeépített Stream API + automatikus frissítés
KomplexitásAlacsony (ismert SQL)Közepes (saját DSL)
MigrációkKézi SQL szkriptekAutomatikus + kézi
KompatibilitásAndroid, iOS, macOSAndroid, iOS, Web, macOS, Linux

Mikor válasszuk a Floor-t

Floor — azon csapatok választása, akik már ismerik az SQL-t és az Android Room-ot. Ha a fejlesztők hozzászoktak az SQL lekérdezések kézi írásához és minimális burkolót szeretnének az SQLite fölé — a Floor tipizálást biztosít anélkül, hogy új DSL-t kellene tanulni. Emellett könnyebben debugolható, mivel a generált kód olvasható és kiszámítható.

Mikor jobb a Drift

Drift erősebb reaktivitást nyújt és több platformot támogat. Ha az alkalmazás aktívan használja a Stream-et az UI frissítéséhez, összetett lekérdezéseket igényel JOIN-nal és allekérdezésekkel, vagy webre épül — a Drift előnyösebb. Azonban a belépési küszöbe magasabb a saját DSL megtanulásának szükségessége miatt.

Kódpéldák Floor-ral

Floor az annotációk köré épül. Alább egy teljes példa Entity, DAO és Database számára egy feladatlista alkalmazáshoz. A build_runner futtatása után a generált osztályok használatra készek.

Entity és DAO definíció

A TaskEntity osztály a @Entity annotációval a task táblára képeződik le. A @primaryKey mező elsődleges kulccsá válik. A TaskDao interfész metódusokat tartalmaz a tábla műveleteihez — minden metódus @Query, @Insert, @Update vagy @Delete annotációval van ellátva.

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

Adatbázis inicializálása

A @Database annotációval ellátott absztrakt osztály összeköti az Entity-t és a DAO-t. A databaseBuilder metódus létrehozza az adatbázis példányát. A build meghívása után az adatbázis készen áll: a Floor megnyitja az SQLite fájlt, alkalmazza a migrációkat és visszaadja a DAO-t a munkához.

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

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

Reaktív lekérdezések Stream-en keresztül

Floor támogatja a Stream visszaadását a DAO metódusokból. Bármilyen változáskor a táblában a Stream új listát bocsát ki. Ez integrálódik a StreamBuilder-rel Flutterben — az UI automatikusan frissül rekordok hozzáadásakor, módosításakor vagy törlésekor.

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

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

Migrációk és verziókezelés a Floor-ban

Floor támogatja az adatbázis verziókezelését a @Database annotáció version paraméterén keresztül. Az Entity megváltoztatásakor (mezők hozzáadásakor vagy eltávolításakor) növelni kell a verziót és hozzáadni egy migrációt. A migráció egy Dart függvény, amely tranzakciót kap és ALTER TABLE SQL lekérdezéseket hajt végre.

Migrációs példa

Tegyük fel, hogy a 2-es verzióban hozzáadtuk a dueDate mezőt a TaskEntity-hez. A migráció az ALTER TABLE SQL lekérdezéssel történik. Ha a migráció nincs megadva, a Floor meghívja a MigrationStrategy-t, ahol fallback állítható be (például a tábla újra létrehozása adatvesztéssel).

Floor lekérdezések tesztelése

Floor nem biztosít beépített mock keretrendszert, de az adatbázis könnyen helyettesíthető tesztekben. Hozzon létre inMemoryDatabaseBuilder-t — ez egy SQLite adatbázist hoz létre a memóriában, amely sémájában megegyezik a production-nel. Minden teszt után törölje az adatokat a deleteDatabase segítségével a teszt forgatókönyvek elkülönítéséhez.

Tranzakciók és batch műveletek a Floor-ban

Floor támogatja a tranzakciókat a @transaction annotáción keresztül a DAO metóduson. A tranzakción belül több lekérdezés szekvenciálisan hajtódik végre a hiba esetén történő visszagörgetés garanciájával. A batch beszúrás a @Insert segítségével a List<T> paraméterrel optimalizálja több rekord egyetlen hívásban történő beszúrását — ez többször gyorsabb, mint a rekordok egyenkénti beszúrása ciklusban. Tömeges műveletekhez használjon 100–200 rekordos batch beszúrást: ez az optimális egyensúly a végrehajtási sebesség és a RAM fogyasztás között a korlátozott erőforrásokkal rendelkező mobileszközökön.

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

Gyakran Ismételt Kérdések

Miben különbözik a Floor a nyers sqflite-tól?

sqflite az SQL lekérdezések kézi írását és a ResultSet objektumokká alakítását igényli. A Floor ezt a kódot automatikusan generálja: leírja az Entity-t és a DAO-t, a tipizált metódusok pedig kész Dart objektumokat adnak vissza. A Floor az SQL lekérdezéseket is ellenőrzi fordítási időben az annotációkon keresztül.

Támogatja a Floor a táblák közötti kapcsolatokat?

Floor nem rendelkezik beépített annotációkkal a kapcsolatokhoz (ForeignKey, @Relation), mint a Room. A kapcsolatok kézi SQL JOIN lekérdezésekkel valósíthatók meg a @Query-ben. Összetett relációs sémákhoz jobb megfontolni a Drift-et a beépített kapcsolattámogatásával.

Hogyan lehet debugolni a Floor SQL lekérdezéseket?

Floor lehetővé teszi a callback visszahívás engedélyezését a DatabaseBuilder létrehozásakor — ebbe a sqflite.Database példánya kerül átadásra, amelyre naplózó akasztható. Alternatívaként használja a floor_doctor-t a séma és adatok megjelenítéséhez fejlesztői módban.

Használható a Floor webes buildhez?

Floor a sqflite-ot használja, amely nem működik webes környezetben. A webhez külön build szükséges a sqlite3-mal WASM-on keresztül. A jelenlegi verzióban a Floor hivatalosan az Android, iOS és macOS rendszereket támogatja. Webhez használja a Drift-et a sqlite3 adapterrel.

Hogyan működik a lekérdezés-gyorsítótárazás a Floor-ban?

Floor nem rendelkezik beépített gyorsítótárazással — minden lekérdezés az SQLite-hoz hajtódik végre. Az ismétlődő lekérdezések gyorsítótárazásához használjon Repository réteget memóriabeli gyorsítótárral (például dart_cache). A Floor csak kódot generál az SQLite-tal való munkához, anélkül, hogy rétegeket adna hozzá.

Összegzés

  • Floor — ORM az SQLite fölött Entity, DAO és Database kódgenerálással annotációkon keresztül
  • Típusbiztonság — SQL lekérdezések fordítási időben ellenőrizve a @Query annotáción keresztül
  • DAO minta — SQL lekérdezések Dart metódusokba kapszulázva, elválasztva a modellt és a logikát
  • Migrációk — séma verziókezelés Migration segítségével kézi ALTER TABLE-lel
  • Reaktivitás — Stream a DAO-ból az UI automatikus frissítéséhez változásokkor
  • Korlátozások — nincs beépített kapcsolat, nem támogatja a webes build-et
  • Ajánlás — válassza a Floor-t Flutter projektekhez, ahol a csapat ismeri az SQL-t és a Room megközelítést

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is