Drift (Moor) — nedir, reaktif ORM ve veritabanlarıyla çalışma

Yazar: IT Sectr Yayınlanma: 2026-03-13 Okuma süresi: 9 dk

Drift (önceden Moor) Flutter ve Dart için, SQLite üzerine kendi DSL'i ile inşa edilmiş reaktif bir ORM'dir. Geleneksel ORM'lerin aksine Drift, Dart sorgularını derleme zamanında SQL'e derleyerek çalışma zamanı hatalarını ortadan kaldırır. Drift Docs, 2024'e göre Drift, manuel SQL sorgularından %40 daha fazla kod üretir ancak manuel SQL yazmayı tamamen ortadan kaldırarak yerine tür güvenli Dart sözdizimi koyar.

Önemli noktalar

  • Drift — sorguları derleme zamanında SQL'e derleyen reaktif ORM
  • DSL sorguları — SQL dizeleri yazmadan Dart'ta akıcı arayüz
  • Tepkisellik — gerçek zamanlı UI güncellemeleri için Stream ve otomatik güncelleme sorguları
  • Platformlar arası — Android, iOS, Web, macOS, Linux, Windows
  • Geçişler — SQL ile otomatik sürümleme ve manuel geçişler

Drift nedir?

Drift Dart ve Flutter için bir ORM'dir, eskiden Moor olarak bilinirdi. 2019'da Simon Binder tarafından geliştirilmiştir ve o zamandan beri birkaç ana sürüm geçirmiştir. Drift, drift_dev ve build_runner kullanarak derleme zamanında Dart sorgularını SQL'e derler, tam tür güvenliği sağlar ve çalışma zamanında SQL sözdizimi hatalarını ortadan kaldırır.

Floor'un aksine Drift, sorguları oluşturmak için kendi DSL'ini (Alan Adına Özgü Dil) kullanır — geliştirici Dart'ta yazar ve üretici bunu SQL'e çevirir. Bu, IDE'nin sözdizimini kontrol etmesine, tablo alanlarını otomatik tamamlamasına ve sorguları bozma korkusu olmadan veri modelini yeniden düzenlemesine olanak tanır.

Drift (2024)'e göre, kütüphane 8000'den fazla Flutter projesinde kullanılmaktadır. Tüm popüler platformları destekler: Android sqflite ile, iOS sqflite ile, web sqlite3 WASM ile, masaüstü sqlite3 yerel sürücüsüyle.

Yeniden adlandırma geçmişi: Moor → Drift

Moor, sürüm 2.0'da (2022) Drift olarak yeniden adlandırıldı. Nedeni, diğer projelerle ad çakışması ve eski koddan uzaklaşma isteğiydi. API uyumlu kaldı: geçiş yapmak için import'u moor'dan drift'e değiştirin ve bağımlılıkları güncelleyin.

Temel özellikler

Drift şunları sağlar: veri değiştiğinde otomatik güncellemeli yerleşik Stream sorguları, geri alma destekli işlem desteği, rawQuery aracılığıyla özel SQL sorguları, mantık kapsüllemesi için DAO deseni, platformlar arası geçişler ve drift_riverpod ile drift_bloc paketleri aracılığıyla Riverpod ve BLoC ile entegrasyon.

Drift nasıl çalışır?

Drift derleme zamanında kod oluşturma kullanır. Geliştirici, @DataClass ek açıklamaları veya Table'ı genişleten Dart sınıfları aracılığıyla tabloları tanımlar. Oluşturucu yardımcı sınıflar oluşturur: Companion (ekleme/güncelleme sırasında null yapılabilir alanlar için), DriftDatabase (giriş noktası) ve DAO uygulamaları.

Drift, SQLite sorgularını doğrudan yürütmez. Bunun yerine, geliştirici Dart'ta şöyle yazar: select(tasks).where(tasks.priority.greaterThan(3)).build(). Oluşturucu bunu SQL'e çevirir ve çalışma zamanında Drift hazır SQL sorgusunu SQLite'a gönderir. Bu, Dart sözdiziminin rahatlığını yerel SQL performansıyla birleştirir.

Sorgu mimarisi

Drift iki sorgu modunu destekler: DSL (önerilen) ve ham SQL. DSL sorguları yazması daha güvenlidir — derleyici alan adlarını, türleri ve uyumluluğu kontrol eder. Ham SQL, DSL tarafından kapsanmayan karmaşık sorgular için gereklidir: pencere işlevleri, özyinelemeli CTE'ler, belirli SQLite uzantıları.

Drift DSL vs SQL: yaklaşım karşılaştırması

Drift sorgu yazmak için iki yol sunar: Dart DSL (yerel) ve ham SQL (karmaşık durumlar için). DSL, senaryoların %90'ı için tercih edilir: daha güvenlidir, daha okunabilirdir ve yeniden düzenlemeyi destekler. Ham SQL yalnızca DSL gerekli yapıyı kapsamadığında kullanılır.

YönDrift DSLDrift'te ham SQL
Tür güvenliğiTam (derleme)Hayır (çalışma zamanı)
Otomatik tamamlamaEvet (IDE)Yalnızca sql dosyalarında
Yeniden düzenlemeOtomatikManuel dize arama
Karmaşık JOIN'lerDesteklenirTam özgürlük
Pencere işlevleriSınırlıTam destek
TepkisellikYerleşik (Stream).watch() aracılığıyla

DSL ne zaman kullanılır

Drift DSL ana çalışma şeklidir. SELECT, INSERT, UPDATE, DELETE, WHERE, ORDER BY, LIMIT, JOIN ve gruplamayı kapsar. Tüm tipik CRUD sorguları için DSL kullanın: daha kısa, daha güvenlidir ve değişikliklerde Stream'i otomatik olarak günceller.

Ham SQL ne zaman kullanılır

Drift'te ham SQL şunlar için gereklidir: özel SQLite işlevleri (FTS5, JSON1), EXISTS ile karmaşık alt sorgular, INSERT OR REPLACE, CASE ile toplu UPDATE ve performansın kritik olduğu ve DSL'nin en uygun yürütme planını üretmediği sorgular. Ham SQL, drift_dev aracılığıyla tür desteğiyle .sql dosyalarına yazılabilir.

Drift ile kod örnekleri

Drift Table'ı genişleten sınıfları veya @DataClass ek açıklamasını kullanır. Aşağıda DSL, ham SQL ve reaktif güncelleme yoluyla sorgular içeren Task modelinin tam bir örneği verilmiştir. build_runner çalıştırıldıktan sonra oluşturulan tüm sınıflar hazırdır.

Tablo ve veritabanı tanımı

Tasks sınıfı Table'ı genişletir ve sütunları tanımlar. Her sütun Column<T> türünde bir ifadedir. Parametreler: withDefault() varsayılan bir değer belirler, autoIncrement() otomatik artışı belirler. Veritabanı, $DriftDatabase'i genişleten soyut bir sınıftır.

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

DSL aracılığıyla CRUD işlemleri

Drift, tablolar için into(tasks).insert(), select(tasks), update(tasks) ve delete(tasks) yöntemlerini oluşturur. Tüm işlemler Future döndürür — SQLite ile çalışmak eş zamansızdır. Değişiklikleri izlemek için .get() yerine .watch() kullanın.

dart
// Ekle
await into(tasks).insert(TasksCompanion.insert(
    title: Value('Bakkal alışverişi yap'),
    priority: Value(3),
));

// Filtreyle okuma
final highPriority = await (select(tasks)
    ..where((t) => t.priority.greaterThan(2))
    ..orderBy([(t) => OrderingTerm(expression: t.priority, mode: OrderingMode.desc)]))
    .get();

// Reaktif izleme
select(tasks).watch().listen((tasksList) {
    // tasksList — List, tablo her değiştiğinde güncellenir
    updateUi(tasksList);
});

Türlenmiş sonuçla ham SQL

Karmaşık sorgular için Drift, türlemeyi korurken ham SQL yazmaya izin verir. customSelect yöntemi bir sorgu dizesi alır ve kod oluşturucu aracılığıyla türlenmiş bir sonuç döndürür. Bu yaklaşım, SQL esnekliğini Drift tür güvenliğiyle birleştirir.

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

Drift'te geçişler ve sürümleme

Drift hem otomatik geçişleri (basit değişiklikler için) hem de manuel geçişleri (karmaşık dönüşümler için) destekler. Veritabanı sürümü AppDatabase yapıcısında ayarlanır. Sürüm eşleşmezse Drift, bekleyen tüm geçişleri sırayla uygular.

Otomatik geçişler

Varsayılan değere sahip bir sütun eklemek için Drift, MigrationStrategy aracılığıyla otomatik olarak bir geçiş oluşturabilir. Değişiklik mevcut verileri bozmuyorsa (null yapılabilir alan ekleme), sürüm kontrolü ve ALTER TABLE yürütmesiyle beforeOpen kullanabilirsiniz.

Manuel geçişler

Karmaşık değişiklikler (tabloyu yeniden adlandırma, verileri birleştirme, sütun türünü değiştirme) için Drift, manuel SQL geçişi gerektirir. Geçişler, veritabanı sınıfındaki migrations parametresi aracılığıyla belirtilir. Her geçiş, from/to numaraları ve SQL sorguları olan bir nesnedir.

Drift ve test etme

Drift, NativeDatabase.memory() aracılığıyla test modunda çalışmayı destekler. Bellek içi veritabanı her testten önce sıfırdan oluşturulur ve sonra yok edilir. Taklit için, taklit edilmiş bir QueryExecutor ile mocktail paketini kullanın. Drift ayrıca geçiş ve sorgu doğrulamasıyla entegrasyon testleri için DatabaseTestHelper sağlar.

Drift'te DAO deseni

Drift, @DriftAccessor ek açıklamasıyla soyut sınıflar aracılığıyla DAO'yu (Veri Erişim Nesnesi) destekler. DAO, bir veya daha fazla tabloya yönelik sorguları kapsüller ve veritabanından ayrı olarak test edilebilir. Database aracılığıyla doğrudan sorguların aksine DAO, sorgu mantığını uygulamanın farklı bölümleri arasında yeniden kullanmaya olanak tanır ve birim testlerini basitleştirir.

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

Sıkça sorulan sorular

Drift, Floor'dan nasıl farklıdır?

Drift, SQL dizeleri yerine kendi DSL'ini kullanarak tam tür güvenliği ve IDE'de otomatik tamamlama sağlar. Floor, @Query ek açıklamasında SQL dizeleri kullanır. Drift ayrıca daha fazla platformu (web dahil) destekler ve Stream aracılığıyla yerleşik tepkiselliğe sahiptir, oysa Floor'da Stream'in manuel olarak bildirilmesi gerekir.

Drift, veri kaybı olmadan geçişleri destekler mi?

Evet, Drift veri korumalı geçişleri destekler. Sütun eklemek için Migration'da addColumn kullanın. Karmaşık dönüşümler (yeniden adlandırma, birleştirme) için geçişin içine ham SQL yazın. Hiçbir geçiş belirtilmezse Drift, şema eşleşmediğinde veritabanını veri kaybıyla yeniden oluşturur.

Drift, build_runner olmadan kullanılabilir mi?

Drift, build_runner ve drift_dev aracılığıyla kod oluşturma gerektirir. Oluşturma olmadan türlenmiş sorgular oluşturmak imkansızdır. Ancak küçük projeler için Drift, sqlparser'ı destekler — otomatik türlemeyle manuel SQL dosyası yazma, ancak bu yine de bir oluşturma adımı gerektirir.

Drift, Riverpod ile nasıl entegre edilir?

Riverpod ile entegrasyon için drift_riverpod paketini kullanın. Database, DAO ve Stream sorguları için sağlayıcılar sunar. Örnek: final tasksProvider = databaseProvider.select((db) => db.select(db.tasks).watch()) — veri değiştiğinde UI otomatik olarak yeniden oluşturulur.

Drift, SQLite şifrelemesini destekler mi?

Drift yerleşik şifrelemeye sahip değildir, ancak SEE (SQLite Encryption Extension) ile özel sqlite3 kütüphanelerini bağlamayı destekler. Mobil platformlar için QueryExecutor olarak sqflite_sqlcipher kullanın — Drift, soyut QueryExecutor aracılığıyla herhangi bir SQLite uygulamasıyla çalışır.

Özet

  • Drift — sorguları derleme zamanında SQL'e derleyen Flutter ve Dart için reaktif ORM
  • DSL sözdizimi — tam tür güvenliği ve IDE'de otomatik tamamlama ile Dart sorguları
  • Tepkisellik — otomatik UI güncellemeleri için Stream ve otomatik güncelleme sorguları
  • Platformlar arası — Android, iOS, Web (WASM), macOS, Linux, Windows
  • Geçişler — basit değişiklikler için otomatik, karmaşık için manuel SQL
  • Ekosisitm — Riverpod (drift_riverpod) ve BLoC (drift_bloc) ile entegrasyon
  • Öneri — tepkisellik, tür güvenliği ve tüm Flutter platformları desteğinin önemli olduğu projeler için Drift'i seçin

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun