Migrating Room databases

As you add and change features in your app, you need to modify your entity classes to reflect these changes. When a user updates to the latest version of your app, you don't want them to lose all of their existing data, especially if you can't recover the data from a remote server.

The Room persistence library allows you to write Migration classes to preserve user data in this manner. Each Migration class specifies a startVersion and endVersion. At runtime, Room runs each Migration class's migrate() method, using the correct order to migrate the database to a later version.

Caution: If you don't provide the necessary migrations, Room rebuilds the database instead, which means you'll lose all of your data in the database.

Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
        .addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
                + "`name` TEXT, PRIMARY KEY(`id`))");

static final Migration MIGRATION_2_3 = new Migration(2, 3) {
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("ALTER TABLE Book "
                + " ADD COLUMN pub_year INTEGER");

Caution: To keep your migration logic functioning as expected, use full queries instead of referencing constants that represent the queries.

After the migration process finishes, Room validates the schema to ensure that the migration occurred correctly. If Room finds a problem, it throws an exception that contains the mismatched information.

Test migrations

Migrations aren't trivial to write, and failure to write them properly could cause a crash loop in your app. To preserve your app's stability, you should test your migrations beforehand. Room provides a testing Maven artifact to assist with this testing process. However, for this artifact to work, you need to export your database's schema.

Export schemas

Upon compilation, Room exports your database's schema information into a JSON file. To export the schema, set the room.schemaLocation annotation processor property in your build.gradle file, as shown in the following code snippet:


```groovy android { ... defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] } } } } ``` You should store the exported JSON files—which represent your database's schema history—in your version control system, as it allows Room to create older versions of your database for testing purposes. To test these migrations, add the **android.arch.persistence.room:testing** Maven artifact from Room into your test dependencies, and add the schema location as an asset folder, as shown in the following code snippet:


```groovy android { ... sourceSets { androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) } } ```

The testing package provides a MigrationTestHelper class, which can read these schema files. It also implements the JUnit4 TestRule interface, so it can manage created databases.

A sample migration test appears in the following code snippet:

public class MigrationTest {
    private static final String TEST_DB = "migration-test";

    public MigrationTestHelper helper;

    public MigrationTest() {
        helper = new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
                new FrameworkSQLiteOpenHelperFactory());

    public void migrate1To2() throws IOException {
        SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 1);

        // db has schema version 1. insert some data using SQL queries.
        // You cannot use DAO classes because they expect the latest schema.

        // Prepare for the next version.

        // Re-open the database with version 2 and provide
        // MIGRATION_1_2 as the migration process.
        db = helper.runMigrationsAndValidate(TEST_DB, 2, true, MIGRATION_1_2);

        // MigrationTestHelper automatically verifies the schema changes,
        // but you need to validate that the data was migrated properly.