반응형
Room은 내부 디비 라이브러리로 AAC(Android Architecture Component)중 하나로 많은 분들이 사용하고 있습니다.
>> Gradle 설정 (androidX 기준)
최신버전은 공식 문서를 참고해주세요.
def room_version = "2.2.5"
// room
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
androidTestImplementation "androidx.room:room-testing:$room_version"
// optional - RxJava support for Room
implementation "androidx.room:room-rxjava2:$room_version"
// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"
debugImplementation 'com.amitshekhar.android:debug-db:1.0.6'// room debug tool
// optional - Coroutines support for Room
// implementation "androidx.room:room-coroutines:$room_version"
// Test helpers
testImplementation "androidx.room:room-testing:$room_version"
>> 룸 구성요소
Database
룸의 버전과 Entity, Dao를 정의하고 관리하는 클래스로 룸에 접근할땐 해당 클래스를 거칩니다.
@Database(version = 1, entities = [PlantData.Item::class,DiaryData.Item::class])
abstract class DB : RoomDatabase() {
abstract fun plantDao(): PlantData.DAO
abstract fun diaryDao() : DiaryData.DAO
companion object {
private val dbName = "plantdiary.db"
private var INSTANCE: DB? = null
fun getInstance(context: Context): DB {
return INSTANCE ?: synchronized(DB::class) {
INSTANCE ?: Room.databaseBuilder(
context.applicationContext,
DB::class.java,
dbName
)
.build().also { INSTANCE = it }
}
}
fun destroyInstance() {
INSTANCE = null
}
}
}
Dao
- Database에 접근하는 메소드들을 관리하는 클래스로 쿼리문을 직접 작성할 수 있지만 기본적인 Select, Update, Insert, Delete를 Annotation으로 제공합니다.
- LiveData, Flowable등 다양한 리턴 타입을 제공합니다.
- 같은 아이템을 insert했을시 onConflict로 대체하거나 무시하도록 설정할 수 있습니다.
@Dao
interface DAO : BaseDAO<Item> {
@Query("SELECT * FROM $TABLE_NAME WHERE year = :year AND month = :month AND plantId = :plantId")
fun select(year: Int, month: Int, plantId: Long): LiveData<List<Item>>
@Query("SELECT * FROM $TABLE_NAME WHERE year = :year AND month = :month AND day = :day AND plantId = :plantId")
fun selectForDay(year: Int, month: Int,day: Int, plantId: Long): Flowable<List<Item>>
@Query("DELETE FROM $TABLE_NAME WHERE plantId=:plantId")
fun deleteForPlantId(plantId: Long)
@Query("UPDATE $TABLE_NAME SET content = :content, imgPath = :imgPath, gravity = :gravity WHERE year = :year AND month = :month AND day = :day AND plantId = :plantId")
fun updateDiary(year: Int, month: Int,day: Int, plantId: Long, content: String, imgPath: String, gravity: Int) : Completable
@Query("UPDATE $TABLE_NAME SET isGiveWater = :isGiveWater WHERE year = :year AND month = :month AND day = :day AND plantId = :plantId")
fun updateWater(year: Int, month: Int,day: Int, plantId: Long, isGiveWater: Boolean)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertDiary(item : Item) : Completable
}
Entity
- Database 테이블을 의미한다. 이름을 지정하지 않는 경우 클래스 이름이 Entity의 이름으로 저장되며, 대소문자는 구분하지 않는다.
- data class를 이용해서 생성하며 room에서 접근해야 하기 때문에 private으로 필드를 선언하면 안됩니다.
- PrimaryKey는 필드 앞에 Annotation을 사용하는 방법과 Entity Annotation에 파라미터로 넣어줄수도 있습니다.
- 각 컬럼들도 테이블 명과 같이 별도 이름을 지정하지 않는 경우는 선언된 필드 명의 이름을 따르고, ColumnInfo Annotation을 이용해 이름과 디폴트값 외 기타 설정들을 할 수 있다.
@Entity(tableName = "diary")
data class Item(
@PrimaryKey(autoGenerate = true) var id: Int?= null,
@ColumnInfo(name = "img_path",defaultValue = "")
var imgPath: String? = null,
var content: String? = null,
var year: Int,
var month: Int,
var day: Int,
var gravity : Int? = null,
var plantId: Long? = null,
var isGiveWater : Boolean? = null
)
@Entity(primaryKeys = arrayOf("firstName", "lastName"))
data class User(
val firstName: String?,
val lastName: String?
)
저는 Entity와 Dao를 한 클래스에 생성해서 관리합니다. Entity의 경우 필드만 관리되어 별도로 분리해서 쓰기엔 조금 과한 느낌이고 DAO에서 쿼리를 작성할때 필드들을 참고하기 편합니다.
object DiaryData {
const val TABLE_NAME = "diary"
@Entity(tableName = "diary")
data class Item(
@PrimaryKey(autoGenerate = true) var id: Int?= null,
....
)
@Dao
interface DAO : BaseDAO<Item> {
.....
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertDiary(item : Item) : Completable
}
}
.....
// 실제 사용하기
var selectPlant: MutableLiveData<PlantData.Item> = MutableLiveData()
>> 디버깅
facebook에서 제공하는 steho 라이브러리로 저장된 룸 데이터를 확인할 수 있습니다. 적용 방법은 제 포스팅을 참고해주세요.
mvvm 패턴에 관심을 가지면서 알게된 Room을 도입해서 사용한지 좀 됐지만 이번에 마이그레이션 하면서 겪은 내용들을 정리하면 좋겠다고 생각해 늦게나마 포스팅합니다.
마이그레이션 관련 이슈는 이후에 작성해서 올리도록 하겠습니다.
반응형
'안드로이드 > 코틀린' 카테고리의 다른 글
[Android/Kotlin] Transformations를 사용해 Livedata 활용하기 (0) | 2021.02.10 |
---|---|
[Android/Kotlin] Room 마이그레이션 (0) | 2021.01.27 |
[코틀린]Kotlin Coroutine 사용하기 (2) | 2021.01.18 |
[Android] Notification Group을 이용한 푸시 ui 개선 (0) | 2020.12.28 |
[Android] Coroutine + 위젯 업데이트 하기 (0) | 2020.12.23 |