Floor — co to je, ORM nad SQLite ve Flutter

Autor: IT Sectr Publikováno: 2026-03-13 Doba čtení: 9 min

Floor — ORM (Object-Relational Mapping) pro Flutter, poskytující typovanou vrstvu nad SQLite. Na rozdíl od raw SQLite dotazů Floor generuje DAO třídy z anotovaných Dart modelů. Podle údajů Pub.dev, 2024 je Floor používán ve více než 3500 Flutter projektech a patří mezi tři nejoblíbenější ORM řešení pro lokální ukládání dat vedle drift a hive.

Hlavní body

  • Floor — ORM nad SQLite s generováním kódu DAO a Entity prostřednictvím anotací
  • Typová bezpečnost — dotazy jsou kontrolovány při kompilaci, eliminující runtime chyby SQL
  • DAO vzor — Data Access Object zapouzdřuje SQL dotazy v Dart metodách
  • Migrace — vestavěná podpora verzování SQLite schématu
  • Reaktivita — Flow dotazy přes Stream pro automatickou aktualizaci UI

Co je Floor?

Floor — je ORM knihovna pro Flutter a Dart, postavená na SQLite. Používá anotace k popisu entit (Entity), Data Access Object (DAO) a databáze (Database). Generování kódu se provádí prostřednictvím build_runner a floor_generator — kompilátor vytváří implementace DAO a řídící třídu databáze. Na rozdíl od raw sqflite Floor zcela odstraňuje potřebu ručního převodu ResultSet na Dart objekty, automaticky mapuje sloupce na pole Entity pomocí reflexe typů.

Floor následuje vzor Repository + DAO, známý vývojářům Android z Room. Každá tabulka je reprezentována Dart třídou s anotací @Entity, SQL dotazy jsou seskupeny v rozhraních s anotací @dao a databáze je sestavena v abstraktní třídě s @Database. Tento přístup striktně odděluje datový model a logiku dotazů.

Podle Flutter Pulse (2023) je Floor vybrán ve 28% Flutter projektů, které vyžadují lokální databázi. Hlavní důvody výběru — znalost SQL (není třeba učit se nový dotazovací jazyk) a kontrola dotazů při kompilaci. Kromě toho Floor generuje čitelný kód, který se snadno debuguje na rozdíl od abstraktnějších ORM s vlastním DSL, což snižuje práh vstupu pro nové vývojáře v týmu.

Architektura Floor

Floor se skládá ze tří vrstev: Entity (model tabulky), DAO (rozhraní dotazů) a Database (vstupní bod). Generátor vytváří implementace _$_Entity pro mapování polí a _$_Dao pro provádění SQL. Při změně Entity nebo DAO stačí restartovat build_runner — kód se automaticky aktualizuje. Pro migraci mezi verzemi schématu Floor používá sekvenční čísla verzí, což zaručuje integritu dat při aktualizaci aplikace na zařízeních uživatelů.

Jak Floor funguje ve Flutter?

Floor používá SQLite prostřednictvím balíčku sqflite pro platformní sestavení a sqlite3 pro desktop a web. Při spuštění aplikace Floor vytvoří nebo otevře SQLite soubor, aplikuje migrace a připraví DAO metody pro provádění dotazů. Všechny operace se provádějí asynchronně prostřednictvím Future a Stream.

Generování kódu ve Floor funguje na následujícím principu: parser čte anotace ze zdrojového kódu, vytváří AST (Abstract Syntax Tree) modelů a dotazů, poté generuje Dart soubory s prefixem _$. Generovaný kód zahrnuje mapování ResultSet → Entity a zpět.

Bezpečnost vláken

Floor pracuje s SQLite v jednom izolátu. Všechny dotazy se provádějí asynchronně, ale souběžné zápisy jsou blokovány na úrovni SQLite. Pro transakce se používá anotace @transaction, která zaručuje atomicitu skupiny dotazů a vrácení zpět při chybě.

Floor vs Drift: srovnání ORM pro Flutter

Jak Floor, tak Drift — jsou ORM nad SQLite, ale liší se filozofií. Floor je bližší Room z Androidu, Drift — je reaktivnější s vestavěným Stream API a kompilací dotazů přes SQL soubory. Volba mezi nimi závisí na zkušenostech týmu a požadované reaktivitě.

VlastnostFloorDrift
Typ dotazůSQL řetězce v @QueryDart metody + sql soubory
Generování kódufloor_generator (build_runner)drift_dev (build_runner)
ReaktivitaStream z DAOVestavěné Stream API + auto-updating
SložitostNízká (známé SQL)Střední (vlastní DSL)
MigraceRuční SQL skriptyAutomatické + ruční
KompatibilitaAndroid, iOS, macOSAndroid, iOS, Web, macOS, Linux

Kdy zvolit Floor

Floor — volba týmů, které již znají SQL a Android Room. Pokud jsou vývojáři zvyklí psát SQL dotazy ručně a chtějí minimální obal nad SQLite — Floor poskytuje typování bez učení nového DSL. Je také snadnější na ladění, protože generovaný kód je čitelný a předvídatelný.

Kdy je lepší Drift

Drift poskytuje silnější reaktivitu a podporuje více platforem. Pokud aplikace aktivně používá Stream pro aktualizaci UI, vyžaduje složité dotazy s JOIN a poddotazy nebo je sestavována pro web — Drift je preferovanější. Jeho práh vstupu je však vyšší kvůli nutnosti učení vlastního DSL.

Příklady kódu s Floor

Floor je postaven kolem anotací. Níže je uveden úplný příklad Entity, DAO a Database pro aplikaci seznamu úkolů. Po spuštění build_runner jsou generované třídy připraveny k použití.

Definice Entity a DAO

Třída TaskEntity s anotací @Entity se mapuje na tabulku task. Pole s @primaryKey se stává primárním klíčem. Rozhraní TaskDao obsahuje metody pro operace s tabulkou — každá metoda je anotována @Query, @Insert, @Update nebo @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);
}

Inicializace databáze

Abstraktní třída s anotací @Database spojuje Entity a DAO. Metoda databaseBuilder vytváří instanci databáze. Po zavolání build je databáze připravena: Floor otevře SQLite soubor, aplikuje migrace a vrátí DAO pro práci.

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

// Použití
final database = await $FloorAppDatabase.databaseBuilder('app.db').build();
final taskDao = database.taskDao;
final tasks = await taskDao.getAllTasks();

Reaktivní dotazy přes Stream

Floor podporuje vracení Stream z DAO metod. Při jakýchkoli změnách v tabulce Stream vydá nový seznam. To se integruje s StreamBuilder ve Flutter — UI se automaticky aktualizuje při přidávání, změně nebo mazání záznamů.

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

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

Migrace a verzování ve Floor

Floor podporuje verzování databáze prostřednictvím parametru version v anotaci @Database. Při změně Entity (přidání nebo odebrání polí) je třeba zvýšit verzi a přidat migraci. Migrace je Dart funkce, která obdrží transakci a provádí SQL dotazy ALTER TABLE.

Příklad migrace

Řekněme, že ve verzi 2 jsme přidali pole dueDate do TaskEntity. Migrace se provádí SQL dotazem ALTER TABLE. Pokud migrace není uvedena, Floor zavolá MigrationStrategy, kde lze nastavit fallback (například přetvoření tabulky se ztrátou dat).

Testování Floor dotazů

Floor neposkytuje vestavěný mock framework, ale databázi lze snadno nahradit v testech. Vytvořte inMemoryDatabaseBuilder — vytvoří SQLite databázi v paměti, identickou schématem s produkční. Po každém testu vyčistěte data pomocí deleteDatabase pro izolaci testovacích scénářů.

Transakce a dávkové operace ve Floor

Floor podporuje transakce prostřednictvím anotace @transaction na DAO metodě. Uvnitř transakce se provádí několik dotazů sekvenčně s garancí vrácení zpět při chybě. Dávkové vkládání přes @Insert s parametrem List<T> optimalizuje vkládání více záznamů v jednom volání — to je několikanásobně rychlejší než vkládání po jednom v cyklu. Pro hromadné operace použijte dávkové vkládání po 100–200 záznamech: to je optimální rovnováha mezi rychlostí provádění a spotřebou RAM na mobilních zařízeních s omezenými zdroji.

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

Často kladené dotazy

Čím se Floor liší od raw sqflite?

sqflite vyžaduje ruční psaní SQL dotazů a mapování ResultSet na objekty. Floor generuje tento kód automaticky: popíšete Entity a DAO a typované metody vracejí hotové Dart objekty. Floor také kontroluje SQL dotazy při kompilaci prostřednictvím anotací.

Podporuje Floor vztahy mezi tabulkami?

Floor nemá vestavěné anotace pro vztahy (ForeignKey, @Relation) jako Room. Vztahy jsou implementovány prostřednictvím ručních SQL JOIN dotazů v @Query. Pro složitá relační schémata je lepší zvážit Drift s jeho vestavěnou podporou vztahů.

Jak ladit SQL dotazy Floor?

Floor umožňuje povolit callback callback při vytváření DatabaseBuilder — je mu předána instance sqflite.Database, na kterou lze připojit logger. Alternativně použijte floor_doctor pro vizualizaci schématu a dat v režimu vývoje.

Lze Floor použít pro webové sestavení?

Floor používá sqflite, který nefunguje v webovém prostředí. Pro web je potřeba samostatné sestavení s sqlite3 přes WASM. V aktuální verzi Floor oficiálně podporuje Android, iOS a macOS. Pro web použijte Drift s adaptérem sqlite3.

Jak funguje cachování dotazů ve Floor?

Floor nemá vestavěné cachování — každý dotaz se provádí k SQLite. Pro cachování opakujících se dotazů použijte vrstvu Repository s cache v paměti (například dart_cache). Floor pouze generuje kód pro práci s SQLite, aniž by přidával vrstvy nad ním.

Shrnutí

  • Floor — ORM nad SQLite s generováním kódu Entity, DAO a Database prostřednictvím anotací
  • Typová bezpečnost — SQL dotazy kontrolovány při kompilaci prostřednictvím anotace @Query
  • DAO vzor — SQL dotazy zapouzdřeny v Dart metodách, oddělující model a logiku
  • Migrace — verzování schématu přes Migration s ručním ALTER TABLE
  • Reaktivita — Stream z DAO pro automatickou aktualizaci UI při změnách
  • Omezení — žádné vestavěné vztahy, nepodporuje webové sestavení
  • Doporučení — zvolte Floor pro Flutter projekty, kde tým zná SQL a přístup Room

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také