๐ฑ dreaming DiNO
[Kotlin] Room db Migration ๋ฐฉ๋ฒ + Gson ์ด์ฉํด ๋ค์ํ ํ์ ๋ฐ์ดํฐ ์ ์ฅํ๊ธฐ ๋ณธ๋ฌธ
[Kotlin] Room db Migration ๋ฐฉ๋ฒ + Gson ์ด์ฉํด ๋ค์ํ ํ์ ๋ฐ์ดํฐ ์ ์ฅํ๊ธฐ
MK_____ 2022. 5. 12. 17:23ํ ์ด๋ธ์ ์ฌ์ฉ์๊ฐ ์ถ๊ฐํ ์ฌ์ง์ ์ ์ฅํ๊ธฐ ์ํด image column ์ด ์ถ๊ฐ๋ ํ์์ฑ ์๊น
1. Room์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋๋ ๊ธฐ๋ณธ์ ์ผ๋ก primitive type๊ณผ ๊ทธ wrapping ํ์ ๋ง ์ง์
ํ์ง๋ง ๋๋ image uri์ path๋ฅผ List๋ก ์ ์ฅ์ ํ๋ ค๊ณ ํ๋ค
2. Gson ์ด์ฉํ์ฌ TypeConverter ํด๋์ค ์์ฑ
TypeConverter
Room์ primitive type์ด ์๋ ๋ค๋ฅธ ํ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด์ Room์์ ์ ๊ณตํ๋ TypeConverter ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
class Converters {
@TypeConverter
fun fromTimestamp(value: Long?): Date? {
return value?.let { Date(it) }
}
@TypeConverter
fun dateToTimestamp(date: Date?): Long? {
return date?.time?.toLong()
}
}
์ ์์ค๋ฅผ ์ฐธ๊ณ ๋ก ํด์ ๋ง๋ค์๋ค.
package com.example.memolog.repository
import android.util.Log
import androidx.room.ProvidedTypeConverter
import com.google.gson.Gson
@ProvidedTypeConverter
class StringListTypeConverter(private val gson: Gson) {
@androidx.room.TypeConverter
fun listToJson(value: List<String>?): String? {
return value?.let{ gson.toJson(value) }
}
@androidx.room.TypeConverter
fun jsonToList(value: String?): List<String> {
return if(value?.isEmpty() == true){ // "" ๊ณต๋ฐฑ๊ฐ
Log.d("MemoDebug", "value==$value==")
emptyList()
}else{
gson.fromJson(value, Array<String>::class.java).toList()
}
}
}
** isEmpty() ์ null ์ ์ฐจ์ด
Type๋ณํ ํ ๋ ์๊พธ null์ด ๋ค์ด์์ ์ด๋ป๊ฒ Gson์ด ์ด๋ป๊ฒ ๋ณํํด์ผ ํ ์ง ๋ชฐ๋ผ์ null ์ ์ฒดํฌํ์ด์ผ ํ๋ค.
https://coding-mia.tistory.com/139
[Kotlin] Null vs Empty vs Blank
์ ๊ฐ empty์ blank๊ฐ ๋งค์ผ ํท๊ฐ๋ ค์ ํ์คํ๊ฒ ์ง๊ณ ๋์ด๊ฐ๋ ค๊ณ ํฉ๋๋ค. String Validation ํ์ธ ์ค, ์์ฃผ ์ฌ์ฉํ๋ Null, Empty, Blank์ ์ฐจ์ด๋ฅผ ์์๋ณด๊ฒ ์ต๋๋ค. ์๋์ ์ฝ๋๋ค์ group: org.apache.commons..
coding-mia.tistory.com
3. AppDatabase.kt ๋ฒ์ ์ฌ๋ฆฌ๊ธฐ, ๋ง๋ TypeConverter ์ถ๊ฐ
@Database(
entities = [Memo::class],
version = 2
)
@TypeConverters(
value = [StringListTypeConverter::class]
)
abstract class AppDatabase : RoomDatabase() {
abstract fun memoDao(): MemoDao
}
4. Database ์์ฑํด์ฃผ๋ ๊ณณ ๊ฐ์ column ์ถ๊ฐ, migration ์ ์ ๋ฐ ์ถ๊ฐ
class GlobalApplication: Application() {
companion object{
lateinit var appInstance: GlobalApplication
private set
lateinit var databaseInstance: AppDatabase
private set
fun provideGson(): Gson {
return Gson()
}
private val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE 'memo' ADD COLUMN 'image' TEXT NOT NULL DEFAULT ''")
}
}
}
override fun onCreate() {
super.onCreate()
appInstance = this
databaseInstance = Room.databaseBuilder(
appInstance.applicationContext,
AppDatabase::class.java, "exampleApp.db"
)
//.fallbackToDestructiveMigration() // ์ด์ ์ ์์ฑํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ญ์ ํ ํ ์๋ก์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์์ฑ
.allowMainThreadQueries()
.addTypeConverter(StringListTypeConverter(provideGson()))
.addMigrations(MIGRATION_1_2)
.build()
}
}
์๋ ๋ด ์๋๋ image column ์์ฒด๋ฅผ nullable ๋ก ๋ง๋ค๊ณ ์ถ์๋๋ฐ, ๊ทธ ๋ฐฉ๋ฒ์ ์์ง ์ฐพ์ง ๋ชปํด ์ผ๋จ NOT NULL๋ก DEFAULT ๊ฐ์ '' ๊ณต๋ฐฑ์ ๋ฃ์ด์ฃผ์๋ค.
database.execSQL("ALTER TABLE 'memo' ADD COLUMN 'image' TEXT NOT NULL DEFAULT ''")
<Migration ์ ์ฉ ํ>
๊ธฐ์กด memo data ์์ image ์ปฌ๋ผ์ด ์ถ๊ฐ๋์๋ค.
DEFAULT ๋ก '' ๊ณต๋ฐฑ์ ๋ฃ์๊ธฐ ๋๋ฌธ์ ์๋ฌด ๊ฐ์ด ์๋ค.
์๋ก์ด data๋ฅผ ์ถ๊ฐํ๋๋ [""] ์ด ์ถ๊ฐ๋์๋ค.
memo๋ฅผ insert ํ๋ ๊ณณ์ ์ด๋ ๊ฒ ์ถ๊ฐ ํด์คฌ๋ค. ๊ทธ๋์ [""] ๊ณต๋ฐฑ ๋ฆฌ์คํธ๊ฐ ์ถ๊ฐ ๋์๋ค.
์ถ์ฒ: https://leveloper.tistory.com/215 [๊พธ์คํ๊ฒ]
๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง๋ณํ ์๋ฌ ๋ฌธ์ ํด๊ฒฐ
'Android > Android Studio' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Kotlin] [์๋ฌํด๊ฒฐ] Gson TypeConverter ์ Null ์ฒ๋ฆฌ (Nullable coulmn ์ถ๊ฐ) (0) | 2022.05.16 |
---|---|
[Kotlin] EventBus ์ด์ฉํ์ฌ Activity๋ก ๋ฐ์ data โ Fragment๋ก ์ ๋ฌํ์ฌ ๋ฐ๊ธฐ (0) | 2022.05.13 |
[Kotlin] Null vs Empty vs Blank (0) | 2022.05.12 |
[Kotlin] Glide ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ๋ฒ (0) | 2022.02.09 |
[Kotlin] ImageView์ setImageURI์, Glide (URL, URI ์ฐจ์ด) (0) | 2022.02.09 |