Database migrations are done using Room. These migrations are run when the app is opened for the first time after an update.
- Make required changes to the database schema.
- Increment the database version by 1 in the
AppDatabase
class. Then build the project to generate the new schema file. Which is stored in theapp/schemas
directory. This will be used for testing the migration in later steps. - Create a new migration class
Migration_XX
which extendMigration
class. It takes in start and end versions as parameters. TheXX
indicates the version you are migrating to. You can add the migration steps in themigrate
method. Make sure to run the migration steps indatabase.inTransaction
block to run them in a transaction. We are also annotating the constructor withInject
to provide it as part of Dagger graph, so that we can provide it in the database builder.@Suppress("ClassName") class Migration_100 @Inject constructor() : Migration(99, 100) { override fun migrate(database: SupportSQLiteDatabase) { database.inTransaction { execSQL(""" CREATE TABLE IF NOT EXISTS `NewTable` ( `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`) ) """) } } }
- Add the migration class to the
RoomMigrationsModule
class.@Provides fun databaseMigration( migration_100: Migration_100 ): List<Migration> { return listOf( migration_100 ) }
- Run the app and verify that the migration is successful.
While you can manually verify the database migrations by running the app and verifying the data. It's recommended to write automated tests for migrations.
- Create an integration test in
storage/migrations
package inandroidTest
source. The test should extendBaseDatabaseMigrationTest
class, it takes in a start and end version. The test should run the migration steps and verify that the migration is successful.class Migration100AndroidTest : BaseDatabaseMigrationTest(99, 100) { @Test fun migration_should_create_new_table() { // Verify migration steps here } }
- In the test function you can access
before
andafter
database instances. Thebefore
database instance is the database before the migration and theafter
database instance is the database after the migration. You can use these instances to verify that the migration is successful.before.assertTableDoesNotExist("NewTable") after.assertTableExists("NewTable")