데이터베이스 프로그래밍이란 데이터베이스에 테이블을 만들고
SQL을 이용해 데이터를 삽입, 조회, 갱신, 삭제하는 방법이다
안드로이드폰에서 이용하는 데이터 베이스 관리 시스템은
오픈소스로 만들어진 SQLite이다.
<SQLite>
- 테이블의 데이터를 앱의 저장소에 파일로 저장한다
- 외부 앱에서는 접근할 수 없다
- 코드에서는 SQL 질의문만 작성하면 된다
- 실제 데이터는 SQLite가 관리해준다
<질의문 작성하기>
- SQLite를 작성하려면 SQLiteDatabase라는 API를 이용해야 한다.
- SQLiteDatabase 객체는 openCreateDatabase() 함수를 호출해서 얻는다.
val db = openCreateDatabase("testdb", Context.MODE_PRIVATE, null)
- openCreateDatabase() 함수
- 첫 번째 매개변수로 전달한 DB 파일을 연다
- SQLiteDatabase 객체를 돌려준다
- 만약 파일이 없으면 새로 만든다
- SQLiteDatabase 객체에 정의된 다음 함수를 이용하면 질의문을 실행할 수 있다.
public void execSQL(String sql, Object[] bingArgs)
public Cursor rawQuery(String sql, String[] selectionArgs)
- execSQL(), rawQuery() 함수
- 첫 번째 매개변수에 질의문을 전달한다
- 두 번째 매개변수에 질의문에서 ?문자에 대응하는 값을 배열로 전달한다.
- 예를 들어 질의문에 물음표를 3개 작성했다면 크기가 3인 배열을 전달해 순서대로 물음표로 표시한 곳에 대입한다.
- execSQL() 함수
- 질의문 중에서 create, alter, drop, insert, update, delete 문을 실행하는 함수
db.execSQL("create table USER_TB (" + "_id integer primary key autoincrement," + "name not null, " + "phone)")
- 위의 코드는 db 객체가 가리키는 DB파일에 execSQL() 함수로 create 문을 실행해 테이블을 만드는 예이다.
- 이렇게 만든 테이블에 데이터를 넣으려면 다음처럼 execSQL() 함수로 insert문을 실행하면 된다.
db.execSQL("insert into USER_TB (name, phone) values (?,?)",
arrayOf<String>("kkang","0101111"))
- 테이블에 저장된 데이터를 조회할 때는 rawQuery() 함수로 select 문을 실행한다.
- rawQuery() 함수의 반환값은 Cursor 객체이다.
- Cursor 객체는 테이블에서 조회한 행의 집합 정도로 생각하면 된다.
val cursor = db.rawQuery("select * from USER_TB", null)
- 조회한 행의 열 데이터를 가져오려면
- 먼저 Cursor 객체로 행을 선택하고
- 그 행의 열 데이터를 가져온다
- Cursor 객체로 행을 선택할 때는 moveTo~로 시작하는 다음 함수를 이용한다
- 이 함수들은 선택한 행이 있으면 true를 반환하고 없으면 false를 반환한다
- public abstract boolean moveToFirst() : 첫번째 행을 선택한다.
- public abstract boolean moveToLast() : 마지막 행을 선택한다.
- public abstract boolean moveToNext() : 다음 행을 선택한다.
- public abstract boolean moveToPosition(int position) : 매개변수로 지정한 위치의 행을 선택한다.
- public abstract boolean moveToPrevious() : 이전 행을 선택한다.
- 이 함수들은 선택한 행이 있으면 true를 반환하고 없으면 false를 반환한다
- Cursor 객체로 선택한 행의 열 데이터를 가져오려면 타입에 따라 getString(), getInt() 등의 함수를 이용한다.
- 이 함수의 매개변수에는 가져올 데이터가 저장된 열의 인덱스를 전달한다.
- public abstract String getString(int columnIndex)
- public abstract int getInt(int columnIndex)
- public abstract double getDouble(int columnIndex)
- 이 함수의 매개변수에는 가져올 데이터가 저장된 열의 인덱스를 전달한다.
while(cursor.moveToNext()){
val name = cursor.getString(0)
val phone = cursor.getString(1)
}
지금까지 질의문을 실행하는 SQLiteDatabase 클래스의 rawQuery(), execSQL() 함수를 살펴보았다.
이 함수를 이용하지 않고 insert(), update(), delete(), query() 함수를 이용해도 된다.
- 이 함수는 질의문의 각 항목을 매개변수로 대입하면 질의문으로 만들어 실행해준다.
- 즉, 질의문을 코드에서 직접 작성하지 않고 항목별 정보만 매개변수로 대입해 주면 된다.
- public long insert(String table, String nullColumnHack, ContentValues values)
- public int update(String table, ContentValues values, String whereClause, String[] whereArgs)
- public int delete(String table, String whereClause, String[] whereArgs)
- public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
- insert(), update() 함수의 매개변수에서 ContentValues 객체는 열 데이터의 집합이다.
- Map 객체처럼 키-값 형태로 데이터 집합을 저장하는데 이때 키에는 테이블의 열 이름을 지정한다
- insert() 함수 예시
val values = ContentValues()
values.put("name", "bak-hwee")
values.put("phone", "0101234")
db.insert("USER_TB", null, values)
- query() 함수 예시
val cursor = db.query("USER_TB", arrayOf<String>("name","phone"), "phone=?", arrayOf<String>("0101234"), null, null, null)
- query() 함수의 각 매개변수는 다음과 같다
- table: 조회할 테이블 명
- columns: 가져올 값이 담긴 열 이름을 배열로 지정
- selection: select 문의 where 절 뒤에 들어갈 문자열
- selectionArgs: 질의문에서 ?에 들어갈 데이터 배열
- groupBy: select 문의 group by 조건
- having: select 문의 having 조건
- orderBy: select 문의 order by 조건
- 위의 예시에서는
- table은 USER_TB
- columns는 arrayOf<String>("name","phone")
- selection은 "phone=?"
- selectionArgs는 arrayOf<String>("0101234")
- 나머지는 null
<데이터베이스 관리하기>
- SQLite 데이터베이스를 이용할 때는 질의문을 실행해야 하므로 반드시 SQLiteDatabase 객체를 이용해야 한다.
- 추가로 SQLiteOpenHelper 클래스를 이용하면 데이터베이스 프로그램을 좀 더 구조적으로 작성할 수 있다.
- SQLiteOpenHelper 클래스
- 데이터베이스를 관리하는 코드를 추상화 한다.
- 데이터베이스를 관리하는 코드란 테이블을 생성하거나 변경, 제거하는 코드
- 이런 관리 코드는 SQLiteOpenHelper 클래스에 작성하고
- 데이터를 조작하는 코드는 실제 필요한 곳에 작성해 성격이 다른 두 코드를 분리할 수 있다.
- SQLiteOpenHelper는 추상 클래스 이므로 이를 상속받아 하위 클래스를 작성해야 한다.
- 데이터베이스를 관리하는 코드를 추상화 한다.
[Kotlin] 클래스 6—인터페이스(interface), 추상 클래스(abstract class)
Kotlin에서 interface와 abstract class를 정의하고 사용하는 방법과 이들의 특징에 대하여 다룹니다.
medium.com
class DBHelper(context: Context) : SQLiteOpenHelper(context, "testdb", null, 1){
override fun onCreate(db: SQLiteDatabase?){
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int){
}
}
- SQLiteOpenHelper 클래스를 상속 받을 때 상위 클래스의 생성자를 호출하면서 적절한 정보를 남겨줘야 한다
- 위 코드에서 "testDB"는 DB 파일명
- 1은 개발자가 숫자로 지정하는 DB 버전 정보
- onCreate(), onUpgrade() 함수는 SQLiteOpenHelper의 추상 함수이므로 하위 클래스에서 반드시 재정의 해야한다.
- onCreate(): 앱이 설치된 후 SQLiteOpenHelper클래스가 이용되는 순간 한 번 호출한다
- 이 함수에는 데이터베이스의 테이블을 생성하는 코드를 주로 작성한다.
- onUpgrade(): 생성자에 지정한 DB 버전 정보가 변경될 때마다 호출한다.
- 이 함수에는 테이블의 스키마를 변경하는 코드를 주로 작성한다.
- 스키마: 데이터의 구조나 표현 방법, 관계 등을 나타낸다.
- 이 함수에는 테이블의 스키마를 변경하는 코드를 주로 작성한다.
- onCreate(): 앱이 설치된 후 SQLiteOpenHelper클래스가 이용되는 순간 한 번 호출한다
- 이처럼 테이블을 생성하거나 스키마를 변경하는 코드는 SQLiteOpenHelper에 작성하고
- 데이터를 조작하는 질의문은 다른 곳에서 작성하는 구조로 만든다.
- SQLiteOpenHelper클래스를 이용한다면 질의문을 실행하는 SQLiteDatebase 객체도 SQLiteOpenHelper 클래스를 이용해 생성한다.
val db: SQLiteDatabase = DBHelper(this).writableDatabase
SQLiteOpenHelper클래스의 readableDatabase나 writableDatabase 속성으로 데이터베이스 객체를 생성한다.
'안드로이드' 카테고리의 다른 글
[안드로이드] 버튼 테두리 안 나오는 현상 (0) | 2022.11.06 |
---|---|
[안드로이드] 퍼미션 설정하기 (0) | 2022.07.17 |
[안드로이드] API 레벨 호환성 고려하기 (0) | 2022.07.17 |
[안드로이드] 앱 구성 파일 분석(3) - 메인 환경 파일 (0) | 2022.07.17 |
[안드로이드] 앱 구성 파일 분석(2) - 그래들 빌드 설정 파일 (0) | 2022.07.17 |
댓글