Study Record

[Flutter] 데이터베이스 table 만들기 (drift) 본문

Flutter/라이브러리

[Flutter] 데이터베이스 table 만들기 (drift)

초코초코초코 2023. 3. 24. 20:36
728x90

✍ table 만들기

drift 라이브러리에 table 을 만드는 방법 2가지를 소개하려 한다. sql 언어로 작성된 파일을 만들어 데이터베이스를 클래스에서 파일을 참고하는 방법과 Table 클래스를 상속받은 클래스를 만드는 방법이 있다.

 

 

파일을 사용한 방법

 

./lib/database/tables.drift

CREATE TABLE todos (
    id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
    title TEXT,
    body TEXT,
    category INT REFERENCES categories (id)
);

CREATE TABLE categories (
    id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
    description TEXT
) AS Category;

 

 

 

 

./lib/database/test_database.dart 

@DriftDatabase(include: {"tables.drift"})
class TestDatabase extends _$TestDatabase {
  TestDatabase() : super(_openConnection());

  @override
  int get schemaVersion => 1;
}

LazyDatabase _openConnection() {
  return LazyDatabase(() async {
    final dbFolder = await getApplicationDocumentsDirectory();
    final file = File(p.join(dbFolder.path, 'test_database.sqlite'));
    return NativeDatabase.createInBackground(file);
  });
}

DriftDatabase 어노테이션에 sql 언어로 작성된 파일의 경로를 include 하면 된다. 현재는 같은 경로(./lib/database)에 있으니 파일 이름만 적으면 된다.

 

 

 

Table 클래스를 사용한 방법

파일을 사용한 방법에서 DriftDatabase 어노테이션에 직접 Table 클래스를 입력하면 된다.

class Todos extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 6, max: 32)();
  TextColumn get content => text()();
  IntColumn get category => integer().nullable()();
}

@DriftDatabase(tables: [Todos])
class TestDatabase extends _$TestDatabase {
  TestDatabase() : super(_openConnection());

  @override
  int get schemaVersion => 1;
}

LazyDatabase _openConnection() {
  return LazyDatabase(() async {
    final dbFolder = await getApplicationDocumentsDirectory();
    final file = File(p.join(dbFolder.path, 'test_database.sqlite'));
    return NativeDatabase.createInBackground(file);
  });
}

Table 을 만드는 방법은 Table 을 상속받는 클래스를 만든다. 클래스의 이름이 테이블 이름이 된다. Column 은 뒤에 Column 이 붙은 데이터 타입으로 만들 수 있다. drift 는 테이블 클래스를 상속받은 클래스의 's' 를 제거한 이름으로 데이터 클래스를 만든다. 따라서 이름을 지을때는 주의해야 한다. Cloumn 을 만들 때 무조건 "=>" 연산자를 사용해야 하며 변수 이름이 곧 Column 이름이 된다.

따라서 위의 예시 코드는 Todos 테이블에 id, title, content, category 칼럼 이름을 가진다. 테이블은 반드시 Primary Key 를 가져야 하는데 위의 예시 코드에서는 autoIncrement() 함수가 있는 칼럼은 자동으로 Primary Key 가 된다. 따라서, id 칼럼이 자동으로 Primary Key 가 된다.

 

 

 

😶지원하는 칼럼 타입

테이블 칼럼으로 사용할 수 있는 타입은 다음과 같다.

Dart Type Column
int integer()
BigInt int64()
double real()
bool boolean()
String text()
DateTime dateTime()
Unit8List blob()
Enum intEnum()
Enum textEnum()

 

 

 

😶 데이터 클래스 이름(@DataClassName)

DataClassName 어노테이션을 사용하면 원래는 테이블 클래스의 이름 뒤 's' 를 뺀 이름으로 데이터 클래스가 선언되지만 원하는 이름으로 데이터 클래스의 이름을 지을 수 있다.

@DataClassName('TodoData')
class Todos extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 6, max: 32)();
  TextColumn get content => text()();
  IntColumn get category => integer().nullable()();
}

 

 

😶 테이블 이름 따로 짓기

tableName 으로 변수를 선언하는 것으로 테이블 이름을 클래스 이름(Todos)이 아닌 원하는 이름(TodayDo)으로 지을 수 있다.

class Todos extends Table {
  String get tableName => 'TodayDo';
  ...
}

 

 

😶 Column 이름 따로 짓기

Column 을 선언할 때 named(새로운 Column 이름) 함수를 사용하면 변수 이름이 아닌 named() 에 설정한 이름으로 칼럼 이름을 지을 수 있다. 

class Todos extends Table {
  // 칼럼 이름 : category
  IntColumn get parentCategory => integer().named('category')();
}

 

 

😶 자동 증가(autoIncrement)

Column 값이 자동으로 증가한다. sql 문법의 AUTO INCREMENT 기능과 똑같다. autoIncrement() 함수를 사용하면 된다. 이 함수를 사용하면, 자동으로 Primary Key 로 설정된다. 

class Todos extends Table {
  IntColumn get id => integer().autoIncrement()();
}

 

 

😶 null 가능

Column 을 선언할 때 nullable() 함수를 사용하면 null 을 허용해 준다. 기본은 null 을 허용하지 않는다.

 

class Todos extends Table {
    // category 는 null 이 가능하다.
    IntColumn get category => integer().nullable()();
    // title 은 null 이 불가능하다.
    TextColumn get title => text()();
}

 

 

😶 Column default 값 설정

칼럼에 default 값을 설정할 수 있다. withDefault() 와 clientDefault() 함수가 있는데 withDefault 는 정해진 값밖에 설정하지 못하고 clientDefault 는 동적인 값을 설정할 수 있다.

class Todos extends Table {
  BoolColumn get enabled => boolean().withDefault(const Constant(false))();
  IntColumn get id => integer().clientDefault(() => Random.nextInt(100))();
}

 

 

😶 Primary Key

테이블을 만들 때 항상 Primary Key 가 있어야 한다. primary Key 는 override 해서 Set 형태로 칼럼을 정해주면 된다.

class Todos extends Table {
  IntColumn get id => integer()();
  TextColumn get title => text().withLength(min: 6, max: 32)();
  TextColumn get content => text()();
  IntColumn get category => integer().nullable()();
  
  @override
  Set<Column> get primaryKey => {id, title};
}

 

 

😶 조건 설정(CHECK)

sql 문법의 CHECK 기능과 비슷하게 조건을 설정할 수 있다. check() 함수를 사용하여 여러 가지 조건을 걸 수 있다.

class Todos extends Table {
  IntColumn get category => integer().check(category.isSmallerOrEqual(Constant(5)))();
  DateTimeColumn get creationTime => dateTime().check(
        creationTime.isBetween(
          Constant(DateTime(1950)),
          Constant(DateTime(2000)),
        ),
      )();
}

 

 

 

 

 

Dart tables

Dart tables Further information on defining tables in Dart. This page describes advanced features like constraints, nullability, references and views Prefer sql? If you prefer, you can also declare tables via CREATE TABLE statements. Drift's sql analyzer w

drift.simonbinder.eu

 

728x90