Migration in Room DB

Abhishek Pathak
3 min readDec 9, 2022

--

Based on my personal experience, tackling the SQLite upgrade process can be quite demanding. Therefore, today I decided to explore room database migration as an alternative. During my investigation, I made a few noteworthy observations that I have documented below.

In the context of Room DB, any modifications made to the database schema, such as adding new tables, updating table names or columns, or introducing new columns, are considered part of the migration process.

What Room does in migration under hood

Room provides an abstraction layer to make hide the hectic process of SQLite (onUpgrade of SqliteOpenHelper) by having an Migration class.

What does Migration class contains?

A Migration class defines the actions that should be performed when migrating from one version to another.
For example remaining an table name is also part of Migration class.

Case 1- Forgot to add the database new version : app crashes
When you just updating the existing table schema and forgot to update new version then the result will be an IllegalStateException

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.

Case 2: Version increased, but no migration provided : app crashes

when I had updated the database version from current by 1 and forgot to add migration to database and then expecting the favorable result but unfortunately got a crash IllegalStateException

@Database(entities = [Blog::class], version = 2, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {

java.lang.IllegalStateException: A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration …) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.
at androidx.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:117)

Case 3: version increased, fallback to destructive migration enabled to database builder and results -> database got cleared

I can say this is simply a force update of database or even more over a strict update of schema without caring of data. We can do this thing but not really always.

companion object {
private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context): AppDatabase? {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
context.applicationContext, AppDatabase::class.java,
"blogDB"
).fallbackToDestructiveMigration()
.allowMainThreadQueries().build()
}
return INSTANCE
}
}

When I run the app, I got the result : cleared the old existing data

Case 4: version increased, migration provided : data is kept safe and schema also updated.

First step is to update the Entity if you want to update existing table
then move towards creating a migration file as below

val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("Alter TABLE Blog ADD COLUMN body TEXT ")
}
}

here is the database class by adding migration in builder

@Database(entities = [Blog::class], version = 2, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun getBlogDao(): BlogDao
companion object {
private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context): AppDatabase? {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
context.applicationContext, AppDatabase::class.java,
"blogDB"
).addMigrations(MIGRATION_1_2)
.allowMainThreadQueries().build()
}
return INSTANCE
}
}
}

Thank you for reading my article. I really appreciate your response.

Clap if this article helps you. If I got something wrong, please comment for improve.
let’s connect on
Linkedin , GitHub

--

--