반응형
서버와 통신해서 DB에 데이터를 저장하고 가져올 수도 있지만 앱 내부 DB를 이용하는게 프로젝트 진행에 더 유리한 경우가 있다. 그런 경우에 내부 DB(SQLite DB)에 쉽게 접근하기 위해 사용하는 패키지가 'sqflite'다.
sqflite 패키지 설치
pub.dev에서 'sqflite' 검색 후 해당 버전의 패키지를 설치하면 된다. 나 같은 경우에는 2021년 12월 10일 기준 최신버전인 2.0.1 버전을 설치했다.
path 패키지 설치
내부 데이터베이스의 위치를 정확히 정의해주는 path 패키지도 설치해준다. 이 역시 2021년 12월 10일 기준 최신 버전인 1.8.0 버전으로 설치했다.
DB 연결
class SqliteTestModel {
Database? _database;
Future<Database> get database async {
if (_database != null) return _database!;
return await initDB();
}
initDB() async {
String path = join(await getDatabasesPath(), 'test_database.db');
return await openDatabase(
path,
version: 1,
onCreate: _onCreate,
onUpgrade: _onUpgrade
);
}
}
- 매번 쿼리문을 실행할 때마다 DB 경로에 접근해서 DB를 열게되면 자원낭비이기 때문에 Singleton 패턴을 이용하여 Database 변수를 만들어 주었다.
- 'test_database'라는 이름의 DB를 만들어주었다.
- openDatabase 함수
- path - DB 경로
- version - DB의 업그레이드와 다운그레이드를 수행하기 위해 사용된다.
- onCreate - DB에 해당 테이블이 없으면 생성해준다.
- onUpgrade - 이전 version과 업데이트 된 version을 비교하여 다를 경우 새로 업데이트 된 내용이 적용된다.
테이블 생성
FutureOr<void> _onCreate(Database db, int version) {
String sql = '''
CREATE TABLE testTable(
No INTEGER PRIMARY KEY AUTOINCREMENT,
UserID TEXT,
Content TEXT,
RecordDate DATETIME)
''';
db.execute(sql);
}
FutureOr<void> _onUpgrade(Database db, int oldVersion, int newVersion) {}
- No는 int 타입이며, SQLite에서는INTEGER 타입으로 저장된다. 또한 PRIMARY KEY로 지정을 해주었다.
- No를 AUTOINCREMENT로 설정을 해줌으로써 자동으로 값이 1씩 증가하도록 만들어주었다.
- UserID는 String 타입이며, SQLite에서는 TEXT 타입으로 저장된다.
- RecordDate는 데이터가 INSERT되는 시간을 저장하기 위한 컬럼으로 날짜를 입력하기 위해 DATETIME 타입으로 지정해주었다.
- openDatabase에 들어갈 _onUpgrade 함수는 첫 테이블을 생성하는데 필요없기 때문에 빈 칸으로 냅둔다.
onUpgrade에 대해서는 여기에서!!
2021.12.23 - [플러터] SQLite DB 내용 수정 - Flutter, onUpgrade, sqflite, 데이터베이스, db, database
테이블 생성 확인
Widget _buttonView() {
return SizedBox(
height: 100,
child: Row(
children: [
OutlinedButton(
onPressed: () {
var db = _model.database;
},
child: Text('DB 생성')
)
],
),
);
}
- SQLite 테스트를 하기 위해서 테스트 페이지를 만들었다.
- DB 생성 버튼을 클릭하면 자동으로 테이블이 생성되게 SqliteTestModel의 database 변수를 가져오도록 하였다.
Database Inspector 기능으로 테이블 생성 확인
만약 Database Inspector 기능이 활성화 되어 있지 않다면??
2021.12.12 - Database Inspector 안 보이는 경우 해결방법 - Flutter, Android Studio, 안드로이드 스튜디오
CRUD 기능 만들기
CRUD 기반으로 예제를 만들어보았다.
데이터 모델 정의
class SqliteTest {
final int? No;
final String? UserID;
final String? Content;
final String? RecordDate;
SqliteTest({
this.No,
this.UserID,
this.Content,
this.RecordDate
});
Map<String, dynamic> toMap() => {
'UserID': this.UserID,
'Content': this.Content,
'RecordDate': this.RecordDate
};
}
- 테이블을 만들 때 컬럼 이름과 동일하게 데이터 모델을 정의했다.
- INSERT를 할 때 No 컬럼을 AUTOINCREMENT로 설정해서 값을 넣을 필요는 없지만 추후에 SELECT로 데이터를 가져온 후에 KEY 값으로 접근해야 하는 일이 있을 수 있기 때문에 추가해두었다.
- Database 객체에서 제공하는 insert 함수에 넣을 파라미터 값을 위해서 Map으로 변환해주는 toMap() 함수를 추가해준다.
INSERT 함수 예제
- 위와 같이 '아이디(Test)'와 '내용(테스트 내용1)'을 입력하고 INSERT 버튼을 누르면 테이블에 저장되게 INSERT문을 만들어놓았다.
final _model = SqliteTestModel();
... 생략 ...
OutlinedButton(
onPressed: () async {
String userID = _userID.text;
String content = _content.text;
String recordDate = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now());
await _model.testInsert(SqliteTest(
UserID: userID,
Content: content,
RecordDate: recordDate
));
},
child: Text('INSERT')
),
- 위의 OutlinedButton이 눌렸을 때 이벤트에서는 캡쳐화면과 같이 TextField에 입력된 값이 테이블에 INSERT 하는 로직으로 넘어가게 해준다.
Future<void> testInsert(SqliteTest item) async {
var db = await database;
await db.insert(
'testTable',
item.toMap()
);
}
- 위의 함수는 미리 만들어 두었던 데이터 모델을 기반으로 테이블에 INSERT 하게 해주는 로직이다.
INSERT 함수 결과
SELECT 함수 예제 및 결과
- SELECT 버튼을 클릭하면 테이블에 저장된 내용이 출력되게 만들었다.
final _model = SqliteTestModel();
... 생략 ...
OutlinedButton(
onPressed: () async {
var list = await _model.testSelect();
setState(() {
_result = '';
for (var item in list) {
_result += '${item.No} - ${item.UserID} / ${item.Content} / ${item.RecordDate}\n';
}
});
},
child: Text('SELECT')
)
- SELECT 버튼 클릭 이벤트가 발생하면 SELECT 하는 로직을 통해서 List를 리턴받아온다.
Future<List<SqliteTest>> testSelect() async {
var db = await database;
// testTable 테이블에 있는 모든 field 값을 maps에 저장한다.
final List<Map<String, dynamic>> maps = await db.query('testTable');
return List.generate(maps.length, (index) {
return SqliteTest(
No: maps[index]['No'] as int,
UserID: maps[index]['UserID'] as String,
Content: maps[index]['Content'] as String,
RecordDate: maps[index]['RecordDate'] as String
);
});
}
- db.query 함수의 파라미터에 테이블 명을 입력한 후에 List<Map<String, dynamic>> 형태로 테이블에 있는 값들을 모두 리턴받는다.
- List 형태로 변환시켜주고 리턴시킨다.
UPDATE 함수 예제
- UPDATE 버튼을 클릭하면 No 값이 2인 Field 값의 Content 컬럼을 '테스트 내용222'로 변경해보려 한다.
final _model = SqliteTestModel();
... 생략 ...
OutlinedButton(
onPressed: () async {
int no = int.parse( _no.text);
String userID = _userID.text;
String content = _content.text;
String recordDate = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now());
await _model.testUpdate(SqliteTest(
No: no,
UserID: userID,
Content: content,
RecordDate: recordDate
));
},
child: Text('UPDATE')
)
- UPDATE 버튼 클릭 이벤트가 발생하게 되면 TextField의 값들을 모두 SqliteTest 객체에 저장해서 UPDATE 로직으로 넘겨준다.
Future<void> testUpdate(SqliteTest item) async {
var db = await database;
await db.update(
'testTable',
item.toMap(),
where: 'No = ?',
whereArgs: [item.No]
);
}
- UPDATE하기 위해서 Primary Key인 No 컬럼으로 조건을 넣어주었다.
- SqliteTest의 No를 whereArg로 넘겨 SQL injection을 방지한다.
UPDATE 함수 결과
- Primary Key인 No 컬럼으로 접근해서 Content 내용이 '테스트 내용222'로 변경된 것을 확인할 수 있다.
DELETE 함수 예제
- DELETE 버튼을 클릭하면 No의 값이 2인 Field를 삭제해보려 한다.
final _model = SqliteTestModel();
... 생략 ...
OutlinedButton(
onPressed: () async {
int no = int.parse( _no.text);
await _model.testDelete(no);
},
child: Text('DELETE')
)
- DELETE 버튼 클릭 이벤트가 발생하게 되면 No 값을 DELETE 로직으로 넘겨준다.
Future<void> testDelete(int no) async {
var db = await database;
await db.delete(
'testTable',
where: 'No = ?',
whereArgs: [no]
);
}
- delete 역시 SQL injection을 방지하기 위해 whereArgs에 No 값을 입력해주었다.
DELETE 함수 결과
- DELETE 버튼 클릭 후 No를 입력받는 TextField의 값(2)을 기준으로 테이블에서 해당 Field를 삭제했다.
반응형
'APP > Flutter' 카테고리의 다른 글
[플러터] Admob 보상형 광고 - 애드몹, Flutter (0) | 2022.01.11 |
---|---|
[플러터] Admob 전면 광고 - 애드몹, Flutter (0) | 2022.01.04 |
[플러터] Admob 기본 배너 사용법 - 안드로이드, flutter, 애드몹, 광고 (1) | 2021.12.27 |
[플러터] SQLite DB 내용 수정 - Flutter, onUpgrade, sqflite, 데이터베이스, db, database (1) | 2021.12.23 |
[플러터] Database Inspector 안 보이는 경우 해결방법 - Flutter, Android Studio, 안드로이드 스튜디오 (0) | 2021.12.12 |