Employing Migrations
Simply creating a Migration
as an object
somewhere is necessary but not sufficient to have Room know about performing the migration. Instead, you need to use the addMigrations()
method on RoomDatabase.Builder
to teach Room about your Migration
objects. addMigrations()
accepts a varargs, and so you can pass in one or several Migration
objects as needed.
package com.commonsware.room.migration
import android.content.Context
import androidx.annotation.VisibleForTesting
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
@Database(entities = [NoteEntity::class], version = 2)
abstract class NoteDatabase : RoomDatabase() {
companion object {
fun newTestDatabase(context: Context) = Room.inMemoryDatabaseBuilder(
context,
NoteDatabase::class.java
)
.addMigrations(MIGRATION_1_2)
.build()
}
abstract fun notes(): NoteStore
}
@VisibleForTesting
internal val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE notes ADD COLUMN andNowForSomethingCompletelyDifferent TEXT")
}
}
This version of NoteDatabase
has a companion object
with a newTestDatabase()
function that our tests can use. As part of building the NoteDatabase
instance, we use addMigrations(MIGRATION_1_2)
to teach Room about our Migration
.
Also, note that the version
in the @Database
annotation is 2
. In theory, this module demonstrates an app that has been modified from its original. The code started with the NoteBasics
edition of NoteEntity
:
package com.commonsware.room.notes
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "notes")
data class NoteEntity(
@PrimaryKey val id: String,
val title: String,
val text: String,
val version: Int
)
The Migration
module added a new nullable property to NoteEntity
:
package com.commonsware.room.migration
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "notes")
data class NoteEntity(
@PrimaryKey val id: String,
val title: String,
val text: String,
val version: Int,
val andNowForSomethingCompletelyDifferent: String?
)
That property is the column that we are adding in MIGRATION_1_2
, to handle a user that had been using our app with schema version 1
and now upgrades to a newer copy of our app that uses schema version 2
.
In principle, MIGRATION_1_2
could be private
to NoteDatabase
. However, we want to be able to test our migration, so we have it marked as internal
instead, with the @VisibleForTesting
annotation to help discourage unexpected use.
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.