[AAC] Room 사용법

박진성·2023년 6월 1일
0

여태껏 SharedPreferences 만 이용하여 LocalDB를 활용했었다. 사용은 간편했으나, 사이즈가 큰 데이터 혹은 복잡한 데이터를 저장해야 할때는, 한계가 분명히 존재했다. 해서 SQLite의 업그레이드 버전인 Room 을 공부해야할 필요성이 있었다

초기셋팅

→ 이런식으로 각각 파일을 만들어야 편하다

1. Dpendencies 추가

  • module 범위
plugins {
    ...
    id 'kotlin-kapt'
}

// ROOM
def roomVersion = "2.4.3"

implementation("androidx.room:room-runtime:$roomVersion")
kapt("androidx.room:room-compiler:$roomVersion")

// Coroutine
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0")
  • project 범위
// 이부분 추가
buildscript {
    ext.kotlin_version = "1.6.10"

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

plugins {
    id 'com.android.application' version '7.2.2' apply false
    id 'com.android.library' version '7.2.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

2. Entity 선언

  • 테이블에 저장될 데이터형태 선언
  • Class 생성 → MemoEntity 생성
  • id 값을 꼭 넣어줘야 한다
@Entity(tableName = "memo_table")
class MemoEntity (
    @PrimaryKey(autoGenerate = true)
    val id : Int,
    val text : String,
    val title : String,
    val date : String,
    val time : String,
    val mode : Int
)
  • tableName / PrimaryKey / ColumnInfo / Value 또한 설정 가능
@Entity(tableName = "text_table")
data class TextEntity (

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    var id : Int,
    @ColumnInfo(name = "text")
    var text : String

)

3. DAO 선언

  • 테이블에 접근할 Query문 선언
  • 주로 삽입/삭제/수정 을 기본적으로 선언해놓음
@Dao
interface MemoDao {

    @Query("SELECT * FROM memo_table")
    fun getAllMemo() : List<MemoEntity>

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun addMemo(memoEntity : MemoEntity)

    @Delete
    fun deleteMemo(memoEntity : MemoEntity)
}

4. Database 선언

  • Dao 를 선언해놓은 추상클래스 형태로 선언함
@Database(entities = [MemoEntity::class], version= 1)
abstract class MemoDatabase : RoomDatabase() {

    abstract fun memoDao() : MemoDao

    companion object{

        @Volatile
        private var INSTANCE : MemoDatabase? = null

        fun getDatabase(context : Context) : MemoDatabase{

            return INSTANCE?: synchronized(this){
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    MemoDatabase::class.java,
                    "memo_database"
                )
                    .fallbackToDestructiveMigration()
                    .build()

                INSTANCE = instance
                instance
            }
        }
    }
}

DB 연결 + 활용

1. DB 불러오기

  • 이렇게 db를 사용가능한 상태로 불러옴!
var db: MemoDatabase? = null

override fun onCreate(savedInstanceState: Bundle?) {

    db = MemoDatabase.getDatabase(this)
   
}

2. DAO 활용 동작 수행

  • DB 접근은, 메인 스레드에서 불가함 !

  • 코루틴 사용하여 IO 스레드에서 진행한다

  • 불러온 db 에서 DAO 호출한뒤, 메소드 적용시키기


CoroutineScope(Dispatchers.IO).launch{
    val Datas = db!!.memoDao().getAllMemo()
    for( i in Datas){
        Log.d(TAG,i.text)
    }
}

3. 데이터 형태 및 반환

  • Entity 로 저장되어있는 데이터는, 반환시 List 로 반환됨!
  • 저장할때도 당연히 Entity로 저장해야한다.
  • PrimaryKey 값은 (id) 0으로만 삽입해도, 저장될때 자동으로 unique 값으로 변경되어 저장됨

// MemoDao

@Query("SELECT * FROM memo_table")
fun getAllMemo() : List<MemoEntity>

// Data.kt

// 메모 추가기능
fun plusMemos(data : MemoData){
    memos.add(data)
    val entityData = MemoEntity(0,data.text,data.title,data.date,data.time,data.mode)
    CoroutineScope(Dispatchers.IO).launch{
        db!!.memoDao().addMemo(entityData)
    }
}

Dao 쿼리문

한번에 여러개 삭제

@Query("DELETE FROM memo_table WHERE id IN (:memoIds)")
fun deleteMemo(memoIds: List<Int>)

특정값 받아서, 해당 행 삭제

@Query("DELETE FROM memo_table WHERE id = :memoId")
fun deleteMemo(memoId: Int)

삽입

  • onConflict 부분은, 만약 값이 겹쳤을때 어떻게 처리할건지 정의한다
  • OnConflictStrategy.IGNORE : 무시
  • OnConflicStrategy.REPLACE : 대체 (덮어쓰기)
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun addMemo(memoEntity : MemoEntity)

수정

→ 방법 1 : Update 활용

  • Entity 안의 primaryKey 가 일치하는 데이터를, 삽입된 데이터로 교체한다

// MemoDao.kt

@Update
fun updateMemo(memoEntity: MemoEntity)
// Data.kt

fun fixMemos(data : MemoData){
    val entityMemo = MemoEntity(data.id,data.text,data.title,data.date,data.time,data.mode)
    CoroutineScope(Dispatchers.IO).launch{
				 db!!.memoDao().updateMemo(entityMemo)
    }
}

→ 방법 2 : Query 활용

  • id 값이 일치하는 행을 수동으로 찾아서, 직접 교체해준다
// MemoDao.kt

@Query("UPDATE memo_table SET text= :text, title= :title, date= :date, time= :time, mode= :mode WHERE id LIKE :memoId")
fun updateMemo( memoId : Int, text : String,title : String,date : String,time : String,mode : Int)
// Data.kt

fun fixMemos(data : MemoData){
    CoroutineScope(Dispatchers.IO).launch{
				 db!!.memoDao().updateMemo(data.id,data.text,data.title,data.date,data.time,data.mode)
    }
}

1. Dpendencies 추가

  • module 범위
plugins {
    ...
    id 'kotlin-kapt'
}

// ROOM
def roomVersion = "2.4.3"

implementation("androidx.room:room-runtime:$roomVersion")
kapt("androidx.room:room-compiler:$roomVersion")

// Coroutine
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0")
  • project 범위
// 이부분 추가
buildscript {
    ext.kotlin_version = "1.6.10"

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

plugins {
    id 'com.android.application' version '7.2.2' apply false
    id 'com.android.library' version '7.2.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

2. Entity 선언

  • 테이블에 저장될 데이터형태 선언
  • Class 생성 → MemoEntity 생성
  • id 값을 꼭 넣어줘야 한다
@Entity(tableName = "memo_table")
class MemoEntity (
    @PrimaryKey(autoGenerate = true)
    val id : Int,
    val text : String,
    val title : String,
    val date : String,
    val time : String,
    val mode : Int
)
  • tableName / PrimaryKey / ColumnInfo / Value 또한 설정 가능
@Entity(tableName = "text_table")
data class TextEntity (

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    var id : Int,
    @ColumnInfo(name = "text")
    var text : String

)

3. DAO 선언

  • 테이블에 접근할 Query문 선언
  • 주로 삽입/삭제/수정 을 기본적으로 선언해놓음
@Dao
interface MemoDao {

    @Query("SELECT * FROM memo_table")
    fun getAllMemo() : List<MemoEntity>

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun addMemo(memoEntity : MemoEntity)

    @Delete
    fun deleteMemo(memoEntity : MemoEntity)
}

4. Database 선언

  • Dao 를 선언해놓은 추상클래스 형태로 선언함
@Database(entities = [MemoEntity::class], version= 1)
abstract class MemoDatabase : RoomDatabase() {

    abstract fun memoDao() : MemoDao

    companion object{

        @Volatile
        private var INSTANCE : MemoDatabase? = null

        fun getDatabase(context : Context) : MemoDatabase{

            return INSTANCE?: synchronized(this){
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    MemoDatabase::class.java,
                    "memo_database"
                )
                    .fallbackToDestructiveMigration()
                    .build()

                INSTANCE = instance
                instance
            }
        }
    }
}

DB 연결 + 활용

1. DB 불러오기

  • 이렇게 db를 사용가능한 상태로 불러옴!
var db: MemoDatabase? = null

override fun onCreate(savedInstanceState: Bundle?) {

    db = MemoDatabase.getDatabase(this)
   
}

2. DAO 활용 동작 수행

  • DB 접근은, 메인 스레드에서 불가함 !

  • 코루틴 사용하여 IO 스레드에서 진행한다

  • 불러온 db 에서 DAO 호출한뒤, 메소드 적용시키기


CoroutineScope(Dispatchers.IO).launch{
    val Datas = db!!.memoDao().getAllMemo()
    for( i in Datas){
        Log.d(TAG,i.text)
    }
}

3. 데이터 형태 및 반환

  • Entity 로 저장되어있는 데이터는, 반환시 List 로 반환됨!
  • 저장할때도 당연히 Entity로 저장해야한다.
  • PrimaryKey 값은 (id) 0으로만 삽입해도, 저장될때 자동으로 unique 값으로 변경되어 저장됨

// MemoDao

@Query("SELECT * FROM memo_table")
fun getAllMemo() : List<MemoEntity>

// Data.kt

// 메모 추가기능
fun plusMemos(data : MemoData){
    memos.add(data)
    val entityData = MemoEntity(0,data.text,data.title,data.date,data.time,data.mode)
    CoroutineScope(Dispatchers.IO).launch{
        db!!.memoDao().addMemo(entityData)
    }
}

Dao 쿼리문

한번에 여러개 삭제

@Query("DELETE FROM memo_table WHERE id IN (:memoIds)")
fun deleteMemo(memoIds: List<Int>)

특정값 받아서, 해당 행 삭제

@Query("DELETE FROM memo_table WHERE id = :memoId")
fun deleteMemo(memoId: Int)

삽입

  • onConflict 부분은, 만약 값이 겹쳤을때 어떻게 처리할건지 정의한다
  • OnConflictStrategy.IGNORE : 무시
  • OnConflicStrategy.REPLACE : 대체 (덮어쓰기)
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun addMemo(memoEntity : MemoEntity)

수정

→ 방법 1 : Update 활용

  • Entity 안의 primaryKey 가 일치하는 데이터를, 삽입된 데이터로 교체한다

// MemoDao.kt

@Update
fun updateMemo(memoEntity: MemoEntity)
// Data.kt

fun fixMemos(data : MemoData){
    val entityMemo = MemoEntity(data.id,data.text,data.title,data.date,data.time,data.mode)
    CoroutineScope(Dispatchers.IO).launch{
				 db!!.memoDao().updateMemo(entityMemo)
    }
}

→ 방법 2 : Query 활용

  • id 값이 일치하는 행을 수동으로 찾아서, 직접 교체해준다
// MemoDao.kt

@Query("UPDATE memo_table SET text= :text, title= :title, date= :date, time= :time, mode= :mode WHERE id LIKE :memoId")
fun updateMemo( memoId : Int, text : String,title : String,date : String,time : String,mode : Int)
// Data.kt

fun fixMemos(data : MemoData){
    CoroutineScope(Dispatchers.IO).launch{
				 db!!.memoDao().updateMemo(data.id,data.text,data.title,data.date,data.time,data.mode)
    }
}
profile
Android Developer

0개의 댓글