Easily move database tables between different rooms

Since version 2.4.0-Alpha01, automatic migration has been added to the Room library, which makes it easier to implement database migration. Historically, whenever your database schema changed, you had to implement a Migration class and inform Room of the actual change, which in most cases involved writing and executing complex SQL queries.

Now, with automatic migration, you can specify which version to migrate from. Room can automatically generate migrators for simple situations, such as adding or dropping columns and creating new database tables. But in ambiguous situations, Room needs some help. You can provide specific specifications — such as renaming or deleting columns/database tables — based on which Room will generate and run the migration action for you. Let’s take a look at some examples, as well as specific performance.

Add automatic elements to automatic migration

For example, we need to add a new column to a table in a database and upgrade the database from version 1 to version 2. Then we need to update the @database annotation with its incremented version number and add automatic migration from version 1 to version 2:

/* Copyright 2020 Google LLC. spdx-license-identifier: apache-2.0 */

@Database( - version = 1, + version = 2, entities = [ Doggos.class ], + autoMigrations = [ + AutoMigration (from = 1, to = 2)+])abstract class DoggosDatabase : RoomDatabase { }
Copy the code

Every time the database version changes again, you simply update the Automignames list to add a new:

/* Copyright 2020 Google LLC. spdx-license-identifier: apache-2.0 */

@Database( - version = 2, + version = 3, entities = [ Doggos.class ], autoMigrations = [ AutoMigration (from = 1, to = 2),
+      AutoMigration (from = 2, to = 3)])abstract class DoggosDatabase : RoomDatabase { }
Copy the code

For entities declared in @Database Schema, such as adding new columns or tables, updating primary keys, foreign keys, or indexes, or changing the default values of columns, Room automatically detects these changes without additional intervention.

⚠️ Please note that, implementationwise, automatic migration of rooms depends on the generated Database schema, so make sure the exportSchema option in @database is true when using autoMigrations. Otherwise, an error will occur: Cannot create auto-migrations when export schema is OFF.

When automatic migration needs help

Automatic migrations of Room cannot detect all possible changes performed on the database, so sometimes they need some help. As a common example, Room has no way of detecting whether a database table or column has been renamed or deleted. In this case, Room throws a compile error and asks you to implement AutoMigrationSpec. This class allows you to specify the type of change to be made, implement an AutoMigrationSpec and annotate it with one or more of the following:

  • @DeleteTable(tableName)
  • @RenameTable(fromTableName, toTableName)
  • @DeleteColumn(tableName, columnName)
  • @RenameColumn(tableName, fromColumnName, toColumnName)

For example, let’s say we rename Doggos’ database table to GoodDoggos. Room cannot detect whether we created the table and deleted the Doggos table, or renamed it and kept all the values.

/* Copyright 2020 Google LLC. spdx-license-identifier: apache-2.0 */

@Database( version = 2, entities = [ GoodDoggos.class ], autoMigrations = [ AutoMigration ( from = 1, to = 2, spec = DoggosDatabase.DoggosAutoMigration::class )])abstract class DoggosDatabase : RoomDatabase {   
  @RenameTable(fromTableName = "Doggos", toTableName = "GoodDoggos")
    class DoggosAutoMigration: AutoMigrationSpec { }
}
Copy the code

Migration vs automatic migration

When to use migration capabilities

Room has provided the Migration class since version 1.0 for manual handle migrations (manually handle migrations) of databases. You need to use this class whenever you want to change a complex database Schema. For example, if we decide to split a table in a database into two different tables, Room cannot detect the split and cannot automatically detect the data that needs to be moved. So at this point, you need to implement a Migration class and add it to the databaseBuilder() via the addMigrations() method.

/* Copyright 2020 Google LLC. spdx-license-identifier: apache-2.0 */ val MIGRATION_1_2 = object: Migration(1, 2) { override fun migrate(database: SupportSQLiteDatabase) { ... } } Room.databaseBuilder(applicationContext, DoggosDatabase::class.java, "doggos-database") .addMigrations(MIGRATION_1_2,) .build()Copy the code

Using Migration and Automatic Migration together

Room allows you to combine migration with automatic migration. For example, migrating from version 1 to version 2 can be done with Migration, and migrating from Version 2 to version 3 can be done with automatic Migration. If you define both Migration and automatic Migration on the same version, only Migration takes effect.

On the underlying implementation, automatic Migration builds a Migration class, so the Migration logic detailed in this article still applies. TL; DR: When the Database is first accessed, Room checks whether the current Database version is different from the one defined in @database. If so, Room will find a migration path from here to there and perform the migration continuously.

Test automatic migration

You can test automatic Migration through MigrationTestHelper test rules, and with the use of Migration in the same way as calling helper. RunMigrationsAndValidate (). For more information on test migrations, you are welcome to check out the documentation: Testing single Migrations.

conclusion

Automatic migration (autoMigration in @Database) allows you to easily deal with Database Schema changes. While Room can handle many basic cases, for deleting or renaming database tables/columns, you still need to implement an AutoMigrationSpec. For the rest, continue with Migrations.

This feature is still in alpha status, and we welcome your positive feedback through issue Tracker to help us do better.