소소한 개발 공부

[Flutter] SQLite 사용하기 본문

개발/앱 개발

[Flutter] SQLite 사용하기

이내내 2022. 2. 19. 09:56

flutter docs 를 보고 작성했습니다.

 

SQLite에 데이터 저장하기

로컬 디바이스에 많은 데이터를 저장하고 쿼리를 요청해야 한다면, 로컬 파일이나 키-값 저장소 대신 데이터베이스를사용해보세요. 일반적으로 데이터베이스는 다른 로컬 솔루션보다 더 빠른

flutter-ko.dev

 

 

 

플러터 SQLite 데이터베이스는 다음과 같이 사용할 수 있다.

1. 의존성 추가.
2. 데이터 모델 정의.
3. 데이터베이스 열기.
4. 테이블 생성.
5. 데이터베이스에 테이블 요소 추가.
6. 테이블 리스트 조회.
7. 데이터베이스에 있는 테이블 수정.
8. 데이터베이스에서 테이블 삭제.

1. dependencies(의존성) 추가는 pubspec.yaml 파일의 dependencies 란에 sqflite를 추가하는 것이다.

dependencies:
  flutter:
    sdk: flutter
  sqflite:
  path:

2. 데이터 모델 정의는 아래의 스크립트처럼 여러 개의 데이터를 갖는 클래스를 정의하는 것이다.

Dog.dart

class Dog {
  final int id;
  final String name;
  final int age;

  Dog({this.id, this.name, this.age});
}

Memo.dart

class Memo {
  final String id;
  final String title;
  final String text;
  final String createTime;
  final String editTime;

  Memo({required this.id, required this.title, required this.text, required this.createTime, required this.editTime});

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'title': title,
      'text': text,
      'createTime': createTime,
      'editTime': editTime,
    };
  }

  @override
  String toString() {
    return 'Memo{id: $id, title: $title, text: $text, createTime: $createTime, editTime: $editTime}';
  }
}

 

3. 데이터를 읽고 쓰기 전에 데이터베이스 연결을 활성화해야 한다.

path 패키지의 path 함수와 sqflite 패키지의 getDatabasesPath()를 조합해 데이터베이스 파일을 위한 경로를 정의한다. openDatabase로 데이터베이스를 연다.

4. 테이블 생성은 onCreate를 사용한다.

Future<Database>의 execute 로 sql문을 작성해 테이블을 생성한다.

var _db;

  Future<Database> get database async {
    if (_db != null) return _db;
    _db = openDatabase(
      // 데이터베이스 경로를 지정합니다. 참고: `path` 패키지의 `join` 함수를 사용하는 것이
      // 각 플랫폼 별로 경로가 제대로 생성됐는지 보장할 수 있는 가장 좋은 방법입니다.
      join(await getDatabasesPath(), 'memos.db'),
      // 데이터베이스가 처음 생성될 때, dog를 저장하기 위한 테이블을 생성합니다.
      onCreate: (db, version) {
        return db.execute(
          "CREATE TABLE memos(id TEXT PRIMARY KEY, title TEXT, text TEXT, createTime TEXT, editTime TEXT)",
        );
      },
      // 버전을 설정하세요. onCreate 함수에서 수행되며 데이터베이스 업그레이드와 다운그레이드를
      // 수행하기 위한 경로를 제공합니다.
      version: 1,
    );
    return _db;
  }

 

5. 데이터베이스에 테이블 요소 추가는 insert문을 사용한다.

우선 클래스를 Map으로 변환하고(클래스 안에 인스턴스를 Map으로 변환하는 toMap 메서드를 추가한다.) 클래스의 인스턴스를 Map에 저장하기 위해 insert()를 사용한다.

class Dog {
  final int id;
  final String name;
  final int age;

  Dog({this.id, this.name, this.age});

  // dog를 Map으로 변환합니다. key는 데이터베이스 컬럼 명과 동일해야 합니다.
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
      'age': age,
    };
  }
}

// 데이터베이스에 dog를 추가하는 함수를 정의합니다
Future<void> insertDog(Dog dog) async {
  // 데이터베이스 reference를 얻습니다.
  final Database db = await database;

  // Dog를 올바른 테이블에 추가합니다. 동일한 dog가 두번 추가되는 경우를 처리하기 위해 
  // `conflictAlgorithm`을 명시할 수 있습니다. 이는 동일한게 들어오면 덮어쓰여지게 합니다.
  await db.insert(
    'dogs',
    dog.toMap(),
    conflictAlgorithm: ConflictAlgorithm.replace,
  );
}

final fido = Dog(
  id: 0, 
  name: 'Fido', 
  age: 35,
);

await insertDog(fido);

 

6. 테이블 안의 특정 요소를 조회하거나 전체 테이블 리스트를 조회할 수 있다. query를 수행해 List<Map>을 얻고 이 Map을 클래스로 변환해 조회한다.

// dogs 테이블의 모든 dog를 얻는 메서드
Future<List<Dog>> dogs() async {
  final Database db = await database;

  // 모든 Dog를 얻기 위해 테이블에 'dogs'를 질의합니다.
  final List<Map<String, dynamic>> maps = await db.query('dogs');

  // List<Map<String, dynamic>를 List<Dog>으로 변환합니다.
  return List.generate(maps.length, (i) {
    return Dog(
      id: maps[i]['id'],
      name: maps[i]['name'],
      age: maps[i]['age'],
    );
  });
}

print(await dogs()); // Fido를 포함한 테이블 리스트를 출력합니다.

 

7. 데이터베이스에 있는 테이블 요소를 수정한다. sqflite 패키지의 update() 메서드를 이용한다.

먼저 클래스의 인스턴스를 Map으로 변환하고 where 조건절을 사용해 특정 요소를 수정할 수 있게 한다.

Future<void> updateDog(Dog dog) async {
  final db = await database;

  // 주어진 Dog를 수정합니다.
  await db.update(
    'dogs',
    dog.toMap(),	// 클래스 인스턴스의 Map화를 수행합니다
    // Dog의 id가 일치하는 지 확인합니다.
    where: "id = ?",
    // Dog의 id를 whereArg로 넘겨 SQL injection을 방지합니다.
    whereArgs: [dog.id],
  );
}

// Fido의 나이를 수정합니다.
await updateDog(Dog(
  id: 0, 
  name: 'Fido', 
  age: 42,
));

// 수정된 결과를 출력합니다.
print(await dogs()); // Fido의 정보를 나이 42와 함께 출력합니다.

 

8. 데이터베이스에서 특정 요소를 삭제한다. sqflite 패키지의 delete() 메서드를 사용한다.

Future<void> deleteDog(int id) async {
  // 데이터베이스 reference를 얻습니다.
  final db = await database;

  // 데이터베이스에서 Dog를 삭제합니다.
  await db.delete(
    'dogs',
    // 특정 dog를 제거하기 위해 `where` 절을 사용하세요
    where: "id = ?",
    // Dog의 id를 where의 인자로 넘겨 SQL injection을 방지합니다.
    whereArgs: [id],
  );
}

 

참고 : 

플러터 Futter에 SQLite 클래스 정의하기-일선스 / Flutter Database (SQLite) 사용하기 (1)-Dalmangyi