Room migrations: Upgrading to versions with breaking changes

Summary

If you started using Room when it was in version below 1.0.0-alpha8, and you wrote it in Kotlin or used the NonNull annotation, you will have to migrate your DB.

This use case has been upgraded from 1.0.0-alpha3 to 1.0.0-alpha8.

Let’s see how we can migrate our Room DB.

Why do we need the migration?

In the new version, Room adds support for the NOT NULL constraint in primitive types or columns annotated with NonNull. See release notes.

That is going to change the schema that Room generates. Because it changes the schema, it also changes the identityHash of the DB and that is used by Room to uniquely identify every DB version. Therefore, we need a migration.

Let’s take a look at an example in Kotlin. This is applicable in Java when you have the field annotated with NonNull. Basically, our entity Game has an attribute that can never be null called gameName:

If you upgrade the Room library to version 1.0.0-alpha8, you can see how the schema has changed (You can see the changes in bold in the code below):

  • It changes the createSql sentence adding it the NOT NULL attribute to all NonNulls fields.
  • Adds the NOT NULL attribute to the fields of that entity.

As we said before, because the schema has changed, the identityHash of the database is going to change as well.

Note: You don’t know where the schema is or how to export it? Check out the documentation in the “Exporting schemas” section.

Let’s migrate it

To migrate the Database we have to go to our Database object and increase the version number:

Now we have to add a migration to the Room DB builder. Whenever we create the instance of the DB, we have to add the migration as follows:

We create an object of the migration in the RoomDB class.

Let’s take a look at how that Migration1To2 object is implemented:

The Migration object

First attempt

First thing that comes to our minds is: “We might not need to do anything! Let’s just provide an empty migration and because the columns are the same, all should work for free”. Wrong! I tried that and it didn’t work, the app crashed when reading the DB.

Right attempt

We need to provide a proper migration and recreate the table. Steps to follow:

  1. Create a temp Table with the new schema. Check the code below, we have to include the NOT NULL here.
  2. Copy everything from the old table to the new one
  3. Drop the old table
  4. Rename the new table to the old one

Note: The class extends from Migration which is provided by the Room library. Notice that we are passing two arguments to the parent constructor. Those numbers indicate the old version of the DB and the new version. In our example, we are going to migrate from version 1 to version 2. You can read more about it in the Room documentation, but basically, the migrate method that we override is going to be executed whenever the migration needs to happen.

Note: Just to make the first step easier, let Android Studio create the new version of the schema and copy it from there.

Testing your Migration

There are great articles explaining how to test your Room migrations. Check out this article by Florina Muntenescu: Link to article here.

Thanks for reading,

Manuel Vicente Vivo

Written by

Android DevRel @ Google

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store