Android

Android Room 데이터베이스 예제

lipnus 2019. 4. 30. 17:07
반응형

Android Room 데이터베이스 예제

공식문서: https://developer.android.com/training/data-storage/room/


Gradle

//room
implementation "android.arch.persistence.room:runtime:1.1.0"
kapt "android.arch.persistence.room:compiler:1.1.0"

//Rx
implementation "io.reactivex.rxjava2:rxandroid:2.0.2"
implementation "io.reactivex.rxjava2:rxjava:2.1.3"
implementation "android.arch.persistence.room:rxjava2:1.1.1"



Entity - Person.kt

@Entity
class Person(
@PrimaryKey(autoGenerate = true)
val id: Int,
val name: String,
val job: String
)

엔티티는 데이터베이스에 저장될 데이터의 형식.

적어도 하나 이상의 PrimaryKey가 필요.

(autoGenerate = true)

이 부분이 있으면 primarykey 자동으로 1씩 증가.





DAO(Data Access Object) - PersonDAO.kt

@Dao
interface PersonDao {

@Query("SELECT * FROM person")
fun getAllPerson(): Flowable<List<Person>>

@Query("DELETE FROM person")
fun clearAll()


//해당 데이터를 추가합니다.

@Insert
fun insert(vararg person: Person)

//헤당 데이터를 업데이트 합니다.
@Update
fun update(vararg person: Person)

//해당 데이터를 삭제합니다.
@Delete
fun delete(vararg person: Person)

}

데이터 접근 객체는 데이터베이스를 통해 수행할 작업을 정의한 클래스.  

데이터의 삽입, 수정, 삭제 작업이나 저장된 데이터를 불러오는 작업 등을 함수 형태로 정의.

Rx에서 사용하는 Observable로 받을 수 있다.


vararg는 가변인자

가변인자는 매개변수의 값을 동적으로 설정할 수 있다

참고:https://kamang-it.tistory.com/entry/Kotlin-11vararg%EA%B0%80%EB%B3%80%EC%9D%B8%EC%9E%90



//이미 저장된 항목이 있을 경우 데이터를 덮어쓴다
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg person: Person)

primaryKey가 겹칠 경우 에러가 발생.

위의 annotation을 사용하면 겹칠때 덮어쓴다.




AppDatabase.kt

@Database(entities = arrayOf(Person::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun personDao(): PersonDao
}

데이터베이스 생성을 위한 추상클래스. 

데이터 클래스의 값중 String, Int, Boolean, Date과 같은 SQL에서 지원하는 데이터 포맷이 아닌 List, Pair 혹은 커스텀 클래스가 포함되어있다면 @TypeConverter Annotation을을 이용하여 정의해주어야 한다.


RoomDatabase를 생성한 후 각 엔티티의 데이터 변경이 있을경우 데이터베이스 추상클래스에서 사용한 Database Annotation의 Version값을 올려줘야 한다.


그리고 addMigration을 통해 추가되는 필드나 삭제되는 필드에 정의해야한다. 

fallbackToDestructiveMigration 옵션을 줄경우 따로 Migration정의를 해주지 않아도 되지만, 이전에 생성한 데이터베이스를 삭제한 후 새로운 데이터베이스를 생성함.





PersonDatabase.kt

@Database(entities = arrayOf(Person::class), version = 1)
abstract class PersonDatabase: RoomDatabase() {
abstract fun getPersonDao(): PersonDao

companion object {

private var INSTANCE: PersonDatabase? = null

fun getInstance(context: Context): PersonDatabase? {

if(INSTANCE == null) {
synchronized(PersonDatabase::class) {
INSTANCE = Room.databaseBuilder(context, PersonDatabase::class.java, "person.db").build()
}
}

return INSTANCE
}

}

}



Insert부분

val person = Person(0, "조보아","배우")


Observable.just(person)
.subscribeOn(Schedulers.io())
.subscribe( {

PersonDatabase.getInstance(context!!)
?.getPersonDao()
?.insert(person)
},
{

Log.e("SSS", it.message)

})



구독하는 부분

PersonDatabase.getInstance(context!!)
?.getPersonDao()
?.getAllPerson()
?.observeOn(AndroidSchedulers.mainThread())
?.doOnSubscribe { } //구독시 사용
?.doOnTerminate { } //구독이 끝났을 때 사용
?.subscribe( {

Log.d("SSS", "======================================")
for(i in it){
Log.d("SSS", "${i.id} ${i.name} ${i.job}")
}

},
{

Log.e("MyTag", it.message)
})

한번만 이렇게 구독해놓으면, DB에 변화가 있을때 마다 subscribe문이 실행된다. 

한번만 하면 됨.

파이어베이스 사용했던거랑 비슷.






참고: https://black-jin0427.tistory.com/53


참고: https://medium.com/harrythegreat/android-room-database-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-f2019cdced0c


반응형