POST

[안드로이드]코틀린 ORM 라이브러리 - ROOM

ORM(Object-Relational Mapping)

ORM 객체(Class)와 관계형 데이터베이스의 데이터(Table)를 매핑하고 변환하는 기술.

데이터베이스에 사용되는 쿼리를 몰라도 코드만으로 데이터베이스를 컨트롤 할 수 있게 해준다

안드로이드는 SQLite에 접근을 할 수 있게 해주는 ORM라이브러리로 ROOM을 제공한다.

 

Room 사용 준비

build.gradle(Module:app) 에서 room 사용 설정을 해주어야 정상적으로 사용이 가능하다.

차례로 아래의 두 과정을 진행 해준다.

1. Plugins

소스코드의 상단에 plugins 항목에 id 'kotlin-kapt'를 추가한다.

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt' // 추가
}

2. Dependencies

소스코드의 하단에 dependencies 항목에 room을 추가하는 코드를 작성한다.

room의 버전이 바뀔 수 있기 때문에 공식 페이지에서 코드를 가져 오는것이 편하다.

구글에 안드로이드 ROOM 검색 또는 (https://developer.android.com/training/data-storage/room?hl=ko)

dependencies {

    def room_version = "2.3.0" // 추가

    implementation "androidx.room:room-runtime:$room_version" // 추가
    kapt "androidx.room:room-compiler:$room_version" // 추가
    // 코드의 앞 annotationnProcessor 부분을 kapt로 바꾸어 주어야한다.

공식 페이지에서 상단 세개의 줄만 사용하지만 밑의 추가 코드를 모두 추가해도 상관은 없다. 

* 어노테이션 프로세싱은 '@명령어' 처럼 주석 형태로 사용하는 문자열을 실제 코드로 생성해줍니다.

* kapt 코틀린에서 사용하기위해서는 kapt로 추가 해야한다.

 

Room 테이블 생성 - 데이터 클래스 생성

번호와, 내용, 날짜를 저장하는 테이블을 예로 들면 아래처럼 작성을 할 수 있다.

@Entity(tableName = "room_memo") // 데이터베이스 테이블 이름 지정, 아래 클래스를 테이블로사용
class RoomMemo (

    @PrimaryKey(autoGenerate = true) //기본키 지정, 값이 없을때 자동 증가된 숫자값을 입력해준다
    @ColumnInfo // 아래 변수를 컬럼 지정
    var no: Long? = null // 번호

    , @ColumnInfo
    var content: String = "" // 내용

    , @ColumnInfo(name = "Date") // 이름을 지정하면 해당이름으로 컬럼이 생성
    var dateTime: Long =0 // 날짜
)

* 테이블 생성시엔 @Entity를 클래스 위에 작성해야한다.

* 각 변수를 컬럼으로 생성하기위해서는 @ColumnInfo를 변수 위에 작성해야한다.

* 각 레코드를 구분하기위해 기본키를 지정해주어야하며, @ColumnInfo 위에 @PrimaryKey를 작성한다.

* autoGenerate 는 해당 값이 null일 경우 자동으로 증가된 숫자값을 지정해준다.

 

Room DAO(Data Access Object) 생성 - 인터페이스 명령메서드 생성

Room은 데이터베이스에서 읽고 쓰는 메서드를 인터페이스 형태로 설계하고 사용한다.

메서드의 내부 코드가 없는 인터페이스를 만들면 자동으로 Room이 코드를 작성하여 사용하기때문에 쉽게 사용이 가능

/* Dao
 Data Access Object의 약어로 데이터베이스에 접근해서
 DML쿼리(SELECT, INSERT, UPDATE, DELETE)를 실행하는 메서드 모음
 데이터 약어인 어노테이션을 붙여주면 Room 이 각 메소드의 코드를 자동으로 만든다

 테이블이 여러개일 경우 여러개의 해당 테이블에 맞는 DAO를 각각 생성 한다.
 DAO는 RoomHelper 로 접근하여 사용 할 수 있다.
 */
@Dao
interface RoomMemoDAO {

    @Query("select * from room_memo") // 쿼리의 경우 직접 쿼리를 작성 할 수 있다.
    fun selectAll(): MutableList<RoomMemo> // 해당값을 List 형태로 불러옴

    @Insert(onConflict = REPLACE) // no에 동일한 값이 입력 되었을 경우 UPDATE 쿼리로 실행
    fun insert(memo: RoomMemo)

    @Delete
    fun delete(memo: RoomMemo)

}

* 마찬가지로 무엇을 하는 명령어인지 어노테이션으로 지정해주어야하며, 단독으로 사용할 수 없어 Helper 클래스를 생성해 Helper 클래스로 접근하여 사용해야한다.

* 어노테이션으로 구분하여 각 메서드의 코드가 짜여집니다.

 

Room Helper 생성 - 추상 클래스 생성(생성된 테이블을 기반으로 데이터베이스를 생성)

생성시 @Database 어노테이션을 사용하며, 추상클래스로 생성한다.

내부의 코드를 Room이 생성 할 수 있도록  RoomDatabase를 상속 받는다.

@Database(entities = arrayOf(RoomMemo::class), version = 1, exportSchema = false)
abstract class RoomHelper :RoomDatabase() {
    abstract fun roomMemoDao(): RoomMemoDAO
}

각각의 파라미터의 역할

* entities: 테이블이 몇개인지 Room에게 알려준다. 테이블이 여러개일 경우 쉼표로 구분한다.

entities = arrayOf(클래스이름1::class,클래스이름2::class, .. )

* version:  앱 업데이트시 Room테이블이 바뀔수 있기 때문에 반드시 지정해야합니다.

   기존 테이블을 수정을 할 수 있게 해줍니다.

* exportSchema: 값이 true일 경우 스키마의 정보를 파일로 출력한다.

* 스키마: 자료 구조의 표현 방법, 데이터의 구조등을 의미

 

데이터베이스 생성 - Room.databaseBuilder

데이터베이스 생성시 Room의 databaseBuilder를 이용해 만들 수 있습니다.

// (context,룸헬퍼클래스, 데이터 베이스 이름-테이블 이름과는 다름)
// 데이터 베이스 생성
helper = Room.databaseBuilder(this, RoomHelper::class.java,"room_db")
    .allowMainThreadQueries() // just study - room은 메인스레드에서 쿼리를 보낼수 없고 서브스레드로 이용
    .build()

* allowMainThreadQueries(): 실제 실무에서 Room은 서브스레드로 쿼리를 보내기때문에 공부시 메인스레드에서 사용하기위해 해당 옵션을 사용한다.

 

Dao를 이용한 데이터베이스 접근

helper.roomDao()로 바로 사용 해도 되지만 코드 자체가 길어지게 되어 따로 변수를 두어 사용하는것이 좋다.

memoDAO = helper.roomMemoDao()

Dao에 작성된 메서드를 호출하여 데이터 베이스에 접근

memoList.addAll(memoDAO.selectAll()) // 메모리스트변수에 데이터베이스의 데이터를 검색해 저장
memoDAO.insert(memo) // 연결된 help를 이용해 memo의 데이터를 가지고 DAO의 insert()호출
helper?.roomMemoDao()?.delete(mMemo!!)

* 각 쿼리의 작성 방법은 간단한문법으로 작성 됩니다.

 @Query("select * from room_memo whare no>3") -> @Query("명령어 컬럼이름 from 테이블이름 whare 조건")

 

 

어노테이션(annotation) 종류

어노테이션 위치 옵션 설명
@Database 클래스 entities, version 데이터베이스
@Entity 클래스 (tableName = "테이블명") 테이블
@ColumnInfo 멤버 변수 (name = "컬럼명") 컬럼
@PrimaryKey 멤버 변수 (autoGenerate = true) 컬럼 옵션
@Dao 인터페이스   실행 메서드 인터페이스
@Query 멤버 메서드 ("쿼리") 쿼리를 직접 작성하고 실행
@Insert 멤버 메서드 (onConflict = REPLACE) 중복시 수정
@Delete 멤버 메서드   삭제