Room Migration 하기

지프치프·2022년 11월 6일
0

Android

목록 보기
56/85
post-thumbnail

“Android 로봇은 Google에서 제작하여 공유한 저작물을 복제하거나 수정한 것으로 Creative Commons 3.0 저작자 표시 라이선스의 약관에 따라 사용되었습니다.”


개요

Room을 사용하다가 테이블에 대해서 수정이 필요할 때가 있다.
단순히 Entity 클래스에서 수정만 하면 된다고 생각하지만
그랬다가는 App에서 Excpetion을 내뿜게 될 것이다.

2022-11-06 18:50:01.921 24542-25488/? E/AndroidRuntime: FATAL EXCEPTION: Thread-9
Process: com.jeepchief.jongpilllogin, PID: 24542
java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.

언제나 무서운 빨간 글자

Entity 수정과 함께 Database 클래스에 Migration을 추가해야한다.
크게 어렵지 않으니 차근차근 알아가보자.

간단하게 Id와 Pw를 가지고있는 테이블에
name이라는 컬럼을 추가하는 샘플로 포스팅 해보겠다.

Entity 수정

@Entity
data class LoginEntity(
    @PrimaryKey(autoGenerate = true)
    var id: Int,

    @ColumnInfo(name = "user_id")
    var userId: String,

    @ColumnInfo(name = "password")
    var pw: String,

	// 새로 추가될 컬럼
    @ColumnInfo(name = "name")
    var name: String
)

새로 추가될 컬럼인 name을 Entity에 추가해준다.

Database 수정

Database 클래스에서 version을 수정해주어야한다.

@Database(entities = [LoginEntity::class], version = 2, exportSchema = false)
abstract class MyRoomDatabase : RoomDatabase() {
	~~중략~~
}

Database 어노테이션 안에 version을 하나 올려주면 된다.
필자는 기존에 1에서 2로 올려줬다.

그리고 테이블을 수정할 쿼리를 담은 Migration 코드를 작성한다.

        private val MIGRATION_1_2 = object : Migration(1, 2) { // (이전버전, 다음버전)
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL("ALTER TABLE 'LoginEntity' ADD COLUMN 'name' TEXT NOT NULL default ''")
            }
        }

변수의 이름은 크게 상관없지만
보통은 MIGRATION_이전버전_다음버전 으로 정의를 많이 한다.

database.execSQL("쿼리")을 작성해주면 Migration 코드는 작성이 끝났다.
이제 build() 호출 전에 addMigration()을 호출해주면 된다.

Room.databaseBuilder(
	context.applicationContext,
	MyRoomDatabase::class.java,
    "jongpill_login.db"
).addMigrations(MIGRATION_1_2).build()

최종 작성된 Database 클래스의 전체 코드는 아래와 같다.

@Database(entities = [LoginEntity::class], version = 2, exportSchema = false)
abstract class MyRoomDatabase : RoomDatabase() {
    abstract fun getLoginDAO() : LoginDAO

    companion object {
        private var instance: MyRoomDatabase? = null

        @Synchronized
        fun getInstance(context: Context) : MyRoomDatabase {
            instance?.let {
                return it
            } ?: run {
                instance = Room.databaseBuilder(
                    context.applicationContext,
                    MyRoomDatabase::class.java,
                    "jongpill_login.db"
                ).addMigrations(MIGRATION_1_2).build()
                return instance!!
            }
        }

        private val MIGRATION_1_2 = object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL("ALTER TABLE 'LoginEntity' ADD COLUMN 'name' TEXT NOT NULL default ''")
            }
        }
    }
}

그리고 아래는 추가된 테스트 값을 넣은 테이블이다.


추가된 name 컬럼이 정상적으로 들어간 것을 확인할 수 있다.
위 기능은 스튜디오 하단의 툴 바에서 App Inspection을 통해 확인할 수 있다.

Automated migrations?

가이드 문서에 따르면
2.4.0-alpha01 버전 이상부터는 Automated Mirgation을 지원한다고 한다.
Migration을 원하는 버전 범위만 명시해주면
컬럼 추가/삭제, 테이블 삭제 같은 간단한 Migration을
Room에서 자동으로 진행해준다.
이는 다음 기회에 포스팅을 해보도록 하겠다.

개인적으로 공부했던 것을 바탕으로 작성하다보니
잘못된 정보가 있을수도 있습니다.
인지하게 되면 추후 수정하겠습니다.
피드백은 언제나 환영합니다.
읽어주셔서 감사합니다.

profile
지프처럼 거침없는 개발을 하고싶은 개발자

0개의 댓글