Using Drift ORM for Type-Safe SQL Queries in Flutter

Summary
Summary
Summary
Summary

This tutorial covers integrating Drift ORM into Flutter mobile development for type-safe SQL. Learn to set up Drift, define tables and DAOs, execute queries, handle migrations, and implement advanced techniques like transactions. Drift’s generated Dart classes guarantee compile-time safety, while its migration strategy preserves data across schema changes, making database management in Flutter apps more maintainable and error-free.

This tutorial covers integrating Drift ORM into Flutter mobile development for type-safe SQL. Learn to set up Drift, define tables and DAOs, execute queries, handle migrations, and implement advanced techniques like transactions. Drift’s generated Dart classes guarantee compile-time safety, while its migration strategy preserves data across schema changes, making database management in Flutter apps more maintainable and error-free.

This tutorial covers integrating Drift ORM into Flutter mobile development for type-safe SQL. Learn to set up Drift, define tables and DAOs, execute queries, handle migrations, and implement advanced techniques like transactions. Drift’s generated Dart classes guarantee compile-time safety, while its migration strategy preserves data across schema changes, making database management in Flutter apps more maintainable and error-free.

This tutorial covers integrating Drift ORM into Flutter mobile development for type-safe SQL. Learn to set up Drift, define tables and DAOs, execute queries, handle migrations, and implement advanced techniques like transactions. Drift’s generated Dart classes guarantee compile-time safety, while its migration strategy preserves data across schema changes, making database management in Flutter apps more maintainable and error-free.

Key insights:
Key insights:
Key insights:
Key insights:
  • Setting Up Drift in Flutter: Configure dependencies and initialize a LazyDatabase for SQLite access.

  • Defining Tables and DAOs: Use Dart classes to declare tables and DAOs for clean, reusable queries.

  • Executing Type-Safe Queries: Write queries with fluent APIs that catch SQL errors at compile time.

  • Handling Migrations: Leverage Drift’s MigrationStrategy to evolve your schema without data loss.

  • Advanced Query Techniques: Perform transactions and custom updates while preserving type safety.

Introduction

Drift is a powerful Dart ORM that brings type-safe SQL to Flutter mobile development. By generating Dart classes from your database schema, Drift eliminates runtime errors caused by malformed SQL. In this tutorial, you’ll learn how to set up Drift in your Flutter project, define tables and DAOs, perform type-safe queries, manage migrations, and leverage advanced techniques for complex data access.

Setting Up Drift in Flutter

First, add the following dependencies in your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  drift: ^2.0.0
  drift_flutter: ^2.0.0

dev_dependencies:
  drift_dev: ^2.0.0
  build_runner

Then create a database file under lib/src/database.dart. Import Drift and initialize a LazyDatabase that uses a platform-specific implementation:

import 'dart:io';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';

LazyDatabase openConnection() {
  return LazyDatabase(() async {
    final file = File('app.sqlite');
    return NativeDatabase(file);
  });
}

Annotate your database class with @DriftDatabase, list your tables, and run flutter pub run build_runner build to generate code.

Defining Tables and DAOs

Drift uses Dart classes to describe your schema. Each table extends Table. Drift generates a companion class and a data class for each table.

import 'package:drift/drift.dart';

class Users extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get name => text().withLength(min: 1, max: 50)();
  DateTimeColumn get joinedAt => dateTime().withDefault(Constant(DateTime.now()))();
}

You can also define DAOs to encapsulate common queries:

@DriftAccessor(tables: [Users])
class UserDao extends DatabaseAccessor<MyDatabase> with _$UserDaoMixin {
  UserDao(MyDatabase db) : super(db);

  Future<int> insertUser(UsersCompanion user) => into(users).insert(user);

  Stream<List<User>> watchAllUsers() => select(users).watch();
}

Executing Type-Safe Queries

Drift’s fluent API ensures your queries are validated at compile time. For example, to fetch users joined after a certain date:

Future<List<User>> getRecentUsers(DateTime since) {
  return (select(users)..where((u) => u.joinedAt.isBiggerThanValue(since)))
      .get();
}

Complex filters and joins are equally straightforward. Use .join() and innerJoin() to combine tables while keeping type safety.

Handling Migrations

As your schema evolves, Drift can apply migrations automatically. Specify a migration strategy in your database class:

@DriftDatabase(tables: [Users])
class MyDatabase extends _$MyDatabase {
  MyDatabase() : super(openConnection());

  @override
  int get schemaVersion => 2;

  @override
  MigrationStrategy get migration => MigrationStrategy(
        onUpgrade: (m, from, to) async {
          if (from == 1) {
            await m.addColumn(users, users.joinedAt);
          }
        },
      );
}

This code ensures existing data is preserved and new columns are applied without manual SQL scripts.

Advanced Query Techniques

For transactions and custom statements, use Drift’s API directly:

Future<void> transferCredits(int fromId, int toId, int amount) {
  return transaction(() async {
    await customUpdate(
      'UPDATE accounts SET balance = balance - ? WHERE id = ?',
      variables: [Variable(amount), Variable(fromId)],
    );
    await customUpdate(
      'UPDATE accounts SET balance = balance + ? WHERE id = ?',
      variables: [Variable(amount), Variable(toId)],
    );
  });
}

For batch inserts or complex joins, Drift maintains compile-time checks and maps results to Dart objects, simplifying error handling in your Flutter app.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

Drift ORM brings robust, type-safe SQL capabilities to Flutter mobile development. From schema definitions and generated DAOs to migrations and advanced queries, Drift streamlines data access and minimizes runtime errors. Integrate Drift in your next project to enjoy compile-time validation, maintainable migrations, and a fluent Dart API for working with SQLite.

Introduction

Drift is a powerful Dart ORM that brings type-safe SQL to Flutter mobile development. By generating Dart classes from your database schema, Drift eliminates runtime errors caused by malformed SQL. In this tutorial, you’ll learn how to set up Drift in your Flutter project, define tables and DAOs, perform type-safe queries, manage migrations, and leverage advanced techniques for complex data access.

Setting Up Drift in Flutter

First, add the following dependencies in your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  drift: ^2.0.0
  drift_flutter: ^2.0.0

dev_dependencies:
  drift_dev: ^2.0.0
  build_runner

Then create a database file under lib/src/database.dart. Import Drift and initialize a LazyDatabase that uses a platform-specific implementation:

import 'dart:io';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';

LazyDatabase openConnection() {
  return LazyDatabase(() async {
    final file = File('app.sqlite');
    return NativeDatabase(file);
  });
}

Annotate your database class with @DriftDatabase, list your tables, and run flutter pub run build_runner build to generate code.

Defining Tables and DAOs

Drift uses Dart classes to describe your schema. Each table extends Table. Drift generates a companion class and a data class for each table.

import 'package:drift/drift.dart';

class Users extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get name => text().withLength(min: 1, max: 50)();
  DateTimeColumn get joinedAt => dateTime().withDefault(Constant(DateTime.now()))();
}

You can also define DAOs to encapsulate common queries:

@DriftAccessor(tables: [Users])
class UserDao extends DatabaseAccessor<MyDatabase> with _$UserDaoMixin {
  UserDao(MyDatabase db) : super(db);

  Future<int> insertUser(UsersCompanion user) => into(users).insert(user);

  Stream<List<User>> watchAllUsers() => select(users).watch();
}

Executing Type-Safe Queries

Drift’s fluent API ensures your queries are validated at compile time. For example, to fetch users joined after a certain date:

Future<List<User>> getRecentUsers(DateTime since) {
  return (select(users)..where((u) => u.joinedAt.isBiggerThanValue(since)))
      .get();
}

Complex filters and joins are equally straightforward. Use .join() and innerJoin() to combine tables while keeping type safety.

Handling Migrations

As your schema evolves, Drift can apply migrations automatically. Specify a migration strategy in your database class:

@DriftDatabase(tables: [Users])
class MyDatabase extends _$MyDatabase {
  MyDatabase() : super(openConnection());

  @override
  int get schemaVersion => 2;

  @override
  MigrationStrategy get migration => MigrationStrategy(
        onUpgrade: (m, from, to) async {
          if (from == 1) {
            await m.addColumn(users, users.joinedAt);
          }
        },
      );
}

This code ensures existing data is preserved and new columns are applied without manual SQL scripts.

Advanced Query Techniques

For transactions and custom statements, use Drift’s API directly:

Future<void> transferCredits(int fromId, int toId, int amount) {
  return transaction(() async {
    await customUpdate(
      'UPDATE accounts SET balance = balance - ? WHERE id = ?',
      variables: [Variable(amount), Variable(fromId)],
    );
    await customUpdate(
      'UPDATE accounts SET balance = balance + ? WHERE id = ?',
      variables: [Variable(amount), Variable(toId)],
    );
  });
}

For batch inserts or complex joins, Drift maintains compile-time checks and maps results to Dart objects, simplifying error handling in your Flutter app.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

Drift ORM brings robust, type-safe SQL capabilities to Flutter mobile development. From schema definitions and generated DAOs to migrations and advanced queries, Drift streamlines data access and minimizes runtime errors. Integrate Drift in your next project to enjoy compile-time validation, maintainable migrations, and a fluent Dart API for working with SQLite.

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Other Insights

Other Insights

Other Insights

Other Insights

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

© Steve • All Rights Reserved 2025

© Steve • All Rights Reserved 2025

© Steve • All Rights Reserved 2025

© Steve • All Rights Reserved 2025

© Steve • All Rights Reserved 2025

© Steve • All Rights Reserved 2025