일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- git
- github
- HTML
- vim
- c# 윈폼
- dart 언어
- 구조체
- gitlab
- 깃
- 유니티
- docker
- Python
- Unity
- c# winform
- 플러터
- 포인터
- jupyter
- Houdini
- C# delegate
- C언어 포인터
- 도커
- Algorithm
- c언어
- Flutter
- 다트 언어
- c#
- c# 추상 클래스
- Data Structure
- C++
- jupyter lab
Archives
- Today
- Total
nomad-programmer
[Programming/Flutter] SQLite를 이용한 데이터 처리 본문
로컬 디바이스에 많은 데이터를 저장하고 쿼리를 요청해야 한다면, 로컬 파일이나 키-값 저장소 대신 데이터베이스를 사용하는 것이 좋다. 일반적으로 데이터베이스는 다른 로컬 솔루션보다 더 빠른 쓰기, 수정, 읽기 성능을 제공한다.
Flutter 앱은 sqflite 플러그인을 통해 SQLite 데이터베이스를 사용할 수 있다.
sqflite | dart |
INTEGER | int |
REAL | num |
TEXT | String |
BLOB | Uint8List |
import 'package:flutter/material.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
void main() async {
// runApp()이 없기때문에 에러 발생한다. 그래서 아래의 코드를 추가해야 한다.
WidgetsFlutterBinding.ensureInitialized();
// 데이터베이스 경로 지정. 참고로 path패키지의 join함수를 사용해야 각 플랫폼마다의
// 경로가 제대로 생성됐는지 보장할 수 있는 가장 좋은 방법이다.
String dbPath = join(await getDatabasesPath(), 'person_database.db');
// 데이터베이스 파일이 존재할 경우, 삭제한다.
if (await databaseExists(dbPath)) {
await deleteDatabase(dbPath);
}
final Future<Database> database = openDatabase(
dbPath,
// 데이터베이스가 처음 생성될 때, person을 저장하기 위한 테이블을 생성한다.
onCreate: (db, version) {
return db.execute(
'CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, age INTEGER, name TEXT)',
);
},
// 비전 설정. onCreate 함수에서 수행되며 데이터베이스 업그레이드와 다운그레이드를
// 수행하기 위한 경로를 제공한다.
version: 1,
);
Future<void> insertPerson(Person person) async {
// 데이터베이스 reference를 얻는다.
final Database db = await database;
// person 테이블에 데이터를 추가한다. 만약 동일한 person이 존재한다면,
// ConflictAlgorithm이 replace이므로 데이터가 덮어씌워진다.
await db.insert('person', person.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace);
}
Future<List<Person>> persons() async {
// 데이터베이스 reference를 얻는다.
final Database db = await database;
// 모든 person을 얻기 위해 DB에 질의한다.
final List<Map<String, dynamic>> maps = await db.query('person');
// List<Map<String, dynamic>>>를 List<Person>으로 변환한다.
return List.generate(maps.length, (i) {
return Person(
id: maps[i]['id'],
age: maps[i]['age'],
name: maps[i]['name'],
);
});
}
Future<void> updatePerson(Person person) async {
// 데이터베이스의 reference를 얻는다.
final Database db = await database;
// 주어진 Person을 수정한다.
await db.update(
'person',
person.toMap(),
// Person의 id가 일치하는 지 확인
where: "id = ?",
// Person의 id를 whereArg로 넘겨 SQL injection을 방지한다.
whereArgs: [person.id],
);
}
Future<void> deletePerson(int id) async {
// 데이터베이스 reference를 얻는다.
final Database db = await database;
// 데이터베이스에서 Person을 삭제한다.
await db.delete(
'person',
where: "id = ?",
// Person의 id를 where의 인자로 넘겨 SQL injection을 방지한다.
whereArgs: [id],
);
}
Future<Person> getId(int age, String name) async {
// 데이터베이스 reference를 얻는다.
final Database db = await database;
List<Map<String, dynamic>> result = await db.query(
'person',
where: "age = ? AND name = ?",
whereArgs: [age, name],
);
// 위의 result와 같다.
// final result = await db.rawQuery(
// 'SELECT * FROM person WHERE age = ? AND name = ?', [age, name]);
return Person.fromJson(result[0]);
}
Person john = Person(age: 25, name: 'John');
// 데이터베이스에 person을 추가한다.
await insertPerson(john);
// person 목록을 출력한다. (현재 john만 존재한다)
print(await persons());
// john의 나이틑 수정한 뒤 데이터베이스에 저장한다.
john = Person(
id: (await getId(john.age, john.name)).id,
age: john.age + 3,
name: john.name,
);
await updatePerson(john);
// john의 수정된 정보 출력
print(await persons());
// john을 데이터베이스에서 제거한다.
await deletePerson(john.id);
// person 목록을 출력 (현재 비어있다)
print(await persons());
}
class Person {
final int id;
final int age;
final String name;
Person({this.id, this.age, this.name});
factory Person.fromJson(Map<String, dynamic> json) {
return Person(
id: json['id'],
age: json['age'],
name: json['name'],
);
}
Map<String, dynamic> toMap() {
return <String, dynamic>{
'id': id,
'age': age,
'name': name,
};
}
// 각 person 정보를 보기 쉽도록 toString 메소드를 오버라이딩하였다.
@override
String toString() {
return 'Person{id: $id, name: $name, age: $age}';
}
}
/* 결과
I/flutter (15523): [Person{id: 1, name: John, age: 25}]
I/flutter (15523): [Person{id: 1, name: John, age: 28}]
I/flutter (15523): []
*/
WHERE 절에 인자를 전달할 때에는 항상 whereArgs를 사용하는 것이 안전하다. 그 이유는, SQL injection 공격으로부터 보호할 수 있기 때문이다.
where: "id = ${person.id}" 와 같은 String interpolation 문법은 사용하지 안된다.
SQL 문법만 알고 있다면 쉽게 사용할 수 있다. 더 많은 Flutter sqflite 정보를 알고 싶다면 아래의 링크로 가서 예제를 살펴보면 되겠다.
'Programming > Flutter' 카테고리의 다른 글
[Flutter] flutter doctor --android-licenses 명령 에러 (0) | 2020.11.13 |
---|---|
[Programming/Flutter] Provider 메소드 확장 (select, read, watch) (0) | 2020.10.28 |
[Programming/Flutter] isolate : 백그라운드에서의 JSON 파싱 (0) | 2020.10.23 |
[Programming/Flutter] CustomPainter를 이용한 차트(그래프) (0) | 2020.10.22 |
[Dart] Unit Test (유닛 테스트) (0) | 2020.10.22 |
Comments