Drift (Moor) — Mi ez, reaktív ORM és adatbázis-kezelés

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

Drift (korábban Moor) — reaktív ORM Flutter és Dart számára, SQLite-ra építve saját DSL-lel a lekérdezésekhez. A hagyományos ORM-ekkel ellentétben a Drift a Dart lekérdezéseket SQL-be fordítja a build folyamat során, kiküszöbölve a futásidejű hibákat. A Drift Docs, 2024 szerint a Drift akár 40%-kal több kódot generál, mint a kézi SQL lekérdezések, de teljesen kiküszöböli a kézi SQL írást, típusbiztos Dart szintaxissal helyettesítve azt.

Főbb pontok

  • Drift — reaktív ORM lekérdezésfordítással SQL-be build időben
  • DSL lekérdezések — fluent interfész Dartban SQL stringek írása nélkül
  • Reaktivitás — Stream és auto-update lekérdezések valós idejű UI frissítésekhez
  • Platformfüggetlenség — Android, iOS, Web, macOS, Linux, Windows
  • Migrációk — automatikus verziókezelés és kézi migrációk SQL-lel

Mi az a Drift?

Drift — ORM Dart és Flutter számára, korábban Moor néven ismert. Simon Binder fejlesztette 2019-ben és azóta több major verzión ment keresztül. A Drift a Dart lekérdezéseket SQL-be fordítja build időben a drift_dev és build_runner segítségével, ami teljes típusbiztonságot nyújt és kiküszöböli az SQL szintaktikai hibákat futásidőben.

A Floor-ral ellentétben a Drift saját DSL-t (Domain-Specific Language) használ a lekérdezések felépítéséhez — a fejlesztő Dart-ban ír, a generátor pedig lefordítja azt SQL-re. Ez lehetővé teszi az IDE számára a szintaxis ellenőrzését, a táblamezők automatikus kiegészítését és az adatmodell refaktorálását anélkül, hogy félteni kellene a lekérdezések eltörésétől.

A Drift (2024) adatai szerint a könyvtárat több mint 8000 Flutter projektben használják. Támogatja az összes népszerű platformot: Android sqflite-en keresztül, iOS sqflite-en keresztül, web sqlite3 WASM-on keresztül, asztali gépeket sqlite3 natív illesztőprogramon keresztül.

Az átnevezés története: Moor → Drift

Moor-t Drift-re nevezték át a 2.0 verzióban (2022). Az ok — névütközés más projektekkel és a vágy, hogy eltávolodjanak a régi kódtól. Az API kompatibilis maradt: a migrációhoz elég az importot moor-ról drift-re cserélni és frissíteni a függőségeket.

Fő képességek

Drift nyújt: beépített Stream lekérdezéseket automatikus frissítéssel adatváltozáskor, tranzakciók támogatását visszagörgetéssel, egyedi SQL lekérdezéseket rawQuery-n keresztül, DAO mintát a logika elkülönítéséhez, platformfüggetlen migrációkat és integrációt Riverpod-del és BLoC-kal a drift_riverpod és drift_bloc csomagokon keresztül.

Hogyan működik a Drift?

Drift kódgenerálást használ fordítási időben. A fejlesztő a táblákat @DataClass annotációkon vagy a Table-t kiterjesztő Dart osztályokon keresztül írja le. A generátor segédosztályokat hoz létre: Companion (nullable mezőkhöz beszúrásnál/frissítésnél), DriftDatabase (belépési pont) és DAO implementációk.

A Drift nem hajtja végre közvetlenül az SQLite lekérdezéseket. Ehelyett a fejlesztő Dart-ban ír: select(tasks).where(tasks.priority.greaterThan(3)).build(). A generátor ezt SQL-re fordítja, futásidőben pedig a Drift egyszerűen elküldi a kész SQL lekérdezést az SQLite-nak. Ez egyesíti a Dart szintaxis kényelmét a natív SQL teljesítményével.

Lekérdezési architektúra

Drift két lekérdezési módot támogat: DSL (ajánlott) és raw SQL. A DSL lekérdezések biztonságosabbak — a fordító ellenőrzi a mezőneveket, típusokat és kompatibilitást. A raw SQL a bonyolult lekérdezésekhez kell, amelyeket a DSL nem fed le: ablakfüggvények, rekurzív CTE, specifikus SQLite kiterjesztések.

Drift DSL vs SQL: a megközelítések összehasonlítása

Drift két módot kínál a lekérdezések írására: Dart DSL (natív) és raw SQL (bonyolult esetekhez). A DSL az esetek 90%-ában előnyösebb: biztonságosabb, olvashatóbb és támogatja a refaktorálást. A raw SQL csak akkor használatos, ha a DSL nem fedi le a szükséges konstrukciót.

SzempontDrift DSLRaw SQL a Drift-ben
TípusbiztonságTeljes (fordítás)Nincs (futásidő)
Automatikus kiegészítésIgen (IDE)Csak .sql fájlokban
RefaktorálásAutomatikusKézi keresés a stringekben
Összetett JOINTámogatottTeljes szabadság
AblakfüggvényekKorlátozottTeljes támogatás
ReaktivitásBeépített (Stream).watch()-on keresztül

Mikor használjuk a DSL-t

Drift DSL — az alapértelmezett munkamód. Lefedi a SELECT, INSERT, UPDATE, DELETE, WHERE, ORDER BY, LIMIT, JOIN és csoportosítást. Minden tipikus CRUD lekérdezéshez használja a DSL-t: rövidebb, biztonságosabb és automatikusan frissíti a Stream-et változások esetén.

Mikor használjunk raw SQL-t

Raw SQL a Drift-ben a következőkhöz kell: egyedi SQLite függvények (FTS5, JSON1), összetett alekérdezések EXISTS-szel, INSERT OR REPLACE, tömeges UPDATE CASE-sel, valamint olyan lekérdezésekhez, ahol a teljesítmény kritikus és a DSL nem generál optimális végrehajtási tervet. A raw SQL írható .sql fájlokban típusos támogatással a drift_dev-n keresztül.

Kódpéldák Drift-tel

Drift osztályokat használ, amelyek a Table-t terjesztik ki, vagy @DataClass annotációt. Alább egy teljes Task modell példa DSL-lel, raw SQL-lel és reaktív frissítéssel. A build_runner futtatása után az összes generált osztály készen áll.

Tábla és adatbázis definiálása

A Tasks osztály kiterjeszti a Table-t és definiálja az oszlopokat. Minden oszlop egy Column<T> típusú kifejezés. Paraméterek: a withDefault() alapértelmezett értéket ad meg, az autoIncrement() autoinkrementációt. Az adatbázis egy abstract osztály, amely a $DriftDatabase-t terjeszti ki.

dart
class Tasks extends Table {
    IntColumn get id => integer().autoIncrement();
    TextColumn get title => text().withDefault(const Constant(''))();
    BoolColumn get isCompleted => boolean().withDefault(const Constant(false))();
    IntColumn get priority => integer().withDefault(const Constant(0))();
}

@DriftDatabase(tables: [Tasks])
class AppDatabase extends $AppDatabase {
    AppDatabase(QueryExecutor e) : super(e);
}

CRUD műveletek DSL-lel

A Drift generálja a into(tasks).insert(), select(tasks), update(tasks) és delete(tasks) metódusokat a táblákhoz. Minden művelet Future-t ad vissza — az SQLite munka aszinkron. A változások követéséhez használja a .watch()-ot a .get() helyett.

dart
// Beszúrás
await into(tasks).insert(TasksCompanion.insert(
    title: Value('Élelmiszerek vásárlása'),
    priority: Value(3),
));

// Olvasás szűréssel
final highPriority = await (select(tasks)
    ..where((t) => t.priority.greaterThan(2))
    ..orderBy([(t) => OrderingTerm(expression: t.priority, mode: OrderingMode.desc)]))
    .get();

// Reaktív megfigyelés
select(tasks).watch().listen((tasksList) {
    // tasksList — List, frissül a tábla minden módosításakor
    updateUi(tasksList);
});

Raw SQL típusos eredménnyel

Összetett lekérdezésekhez a Drift lehetővé teszi a raw SQL írását a típusosság megtartása mellett. A customSelect metódus egy lekérdezés stringet fogad és típusos eredményt ad vissza a kódgenerátoron keresztül. Ez a megközelítés egyesíti az SQL rugalmasságát a Drift típusbiztonságával.

dart
final result = await customSelect(
    'SELECT title, COUNT(*) as cnt FROM tasks GROUP BY title',
    readsFrom: { tasks },
).get();

for (final row in result) {
    print('${row.readString("title")}: ${row.readInt("cnt")}');
}

Migrációk és verziókezelés a Drift-ben

Drift támogatja mind az automatikus migrációkat (egyszerű változtatásokhoz), mind a kézi migrációkat (bonyolult átalakításokhoz). Az adatbázis verzióját az AppDatabase konstruktorában kell beállítani. Ha a verzió nem egyezik, a Drift egymás után alkalmazza az összes függőben lévő migrációt.

Automatikus migrációk

Egy oszlop hozzáadásához alapértelmezett értékkel a Drift automatikusan generálhat migrációt a MigrationStrategy-n keresztül. Ha a változtatás nem sérti a meglévő adatokat (nullable mező hozzáadása), használható a beforeOpen verzióellenőrzéssel és ALTER TABLE végrehajtásával.

Kézi migrációk

Összetett változtatásokhoz (tábla átnevezése, adatok egyesítése, oszloptípus módosítása) a Drift kézi SQL migrációt igényel. A migrációkat a migrations paraméteren keresztül kell megadni az adatbázis osztályban. Minden migráció egy objektum from/to számokkal és SQL lekérdezésekkel.

Drift és tesztelés

Drift támogatja a teszt módban való futtatást a NativeDatabase.memory()-n keresztül. Az adatbázis a memóriában a semmiből jön létre minden teszt előtt és megsemmisül utána. A mockoláshoz használja a mocktail csomagot mocked QueryExecutor-ral. A Drift DatabaseTestHelper-t is biztosít integrációs tesztekhez migrációk és lekérdezések ellenőrzésével.

DAO minta a Drift-ben

Drift támogatja a DAO (Data Access Object) mintát abstract osztályokon keresztül @DriftAccessor annotációval. A DAO egy vagy több tábla lekérdezéseit kapszulázza be és az adatbázistól függetlenül tesztelhető. A Database-en keresztüli közvetlen lekérdezésekkel ellentétben a DAO lehetővé teszi a lekérdezési logika újrafelhasználását az alkalmazás különböző részei között és egyszerűsíti az egységtesztelést.

dart
@DriftDatabase(tables: [Tasks])
class AppDatabase extends $AppDatabase {
    AppDatabase(QueryExecutor e) : super(e) {
        migrations.add(Migration(1, 2, (m) async {
            await m.addColumn(tasks, tasks.dueDate);
            await m.createIndex(tasks.idxPriority);
        }));
    }
}

Gyakran Ismételt Kérdések

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

Drift saját DSL-t használ SQL stringek helyett, ami teljes típusbiztonságot és automatikus kiegészítést biztosít az IDE-ben. A Floor SQL stringeket használ a @Query annotációban. A Drift több platformot is támogat (beleértve a webet) és beépített reaktivitással rendelkezik Stream-en keresztül, míg a Floor-ban a Stream-et kézzel kell deklarálni.

Támogatja a Drift az adatvesztés nélküli migrációkat?

Igen, a Drift támogatja az adatmegőrző migrációkat. Oszlopok hozzáadásához használja az addColumn-t a Migration-ben. Összetett átalakításokhoz (átnevezés, egyesítés) írjon raw SQL-t a migráción belül. Ha nincs migráció megadva, a Drift újra létrehozza az adatbázist adatvesztéssel, ha a séma nem egyezik.

Használható a Drift build_runner nélkül?

Drift kódgenerálást igényel a build_runner és drift_dev segítségével. Generálás nélkül nem lehet típusos lekérdezéseket létrehozni. Kis projektekhez azonban a Drift támogatja a sqlparser-t — SQL fájlok kézi írását automatikus típusosítással, de ehhez is szükség van a generálási lépésre.

Hogyan integrálható a Drift a Riverpod-del?

A Riverpod-del való integrációhoz használja a drift_riverpod csomagot. Provider-eket biztosít Database-hez, DAO-hoz és Stream lekérdezésekhez. Példa: final tasksProvider = databaseProvider.select((db) => db.select(db.tasks).watch()) — a UI automatikusan újraépül adatváltozáskor.

Támogatja a Drift az SQLite titkosítást?

Drift nem rendelkezik beépített titkosítással, de támogatja az egyedi sqlite3 könyvtárak csatlakoztatását SEE (SQLite Encryption Extension) segítségével. Mobilos platformokhoz használja a sqflite_sqlcipher-t QueryExecutor-ként — a Drift bármely SQLite implementációval működik az absztrakt QueryExecutor-on keresztül.

Összefoglalás

  • Drift — reaktív ORM Flutter és Dart számára lekérdezésfordítással SQL-be build időben
  • DSL szintaxis — Dart lekérdezések teljes típusbiztonsággal és automatikus kiegészítéssel az IDE-ben
  • Reaktivitás — Stream és auto-update lekérdezések automatikus UI frissítésekhez
  • Platformfüggetlenség — Android, iOS, Web (WASM), macOS, Linux, Windows
  • Migrációk — automatikus egyszerű változtatásokhoz és kézi SQL összetettekhez
  • Ökoszisztéma — integráció Riverpod-del (drift_riverpod) és BLoC-kal (drift_bloc)
  • Ajánlás — válassza a Drift-ot olyan projektekhez, ahol fontos a reaktivitás, típusbiztonság és az összes Flutter platform támogatása

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