ZOFTINO.COM android and web dev tutorials

Database Migration with Room

It is very common in any application that database tables are altered to introduce new features in applications. If your app uses Room and database tables need to be altered, then you should use migration process to retain data and make application continue to work.

There is one more scenario in which you need to perform migration is when you want your app to migrate to Room from SQLite API. Even though SQLite database is used with both Room and SQLite API, migrating from SQLite API to Room code requires you to not only define components to access SQLite database but also perform certain migration steps.

In my previous article, there is a detailed explanation about Room and steps to use Room.

In this article I am going to show how to perform database migration with Room.

Migrating to Room from SQLite API

If your existing app uses SQLite database, it must be using SQLite API to access SQLite database. Using Room has many advantages over SQLite API like you don’t need to write boilerplate code with Room, Room allows you to abstract database access, you can create reactive applications, and testing, maintaining and enhancing your app will be easy with Room. My previous article Android Room example provide details about using Room in Android.

To migrate to Room from SQLite API, you need to follow below steps.

  1. Add Room libraries to your project.
  2. Create entity class for each table.
  3. Create DAO interface defining database access methods.
  4. Create RoomDatabase class listing entities, specifying database version(current version as used with SQLite API) and adding DAO.
  5. Create database object using Room class.
  6. Get DAO instance from database.
  7. Use DAO to perform database operations.
  8. Remove unused classes related SQLite API.

After implementing above steps, run your app. Your app will crash and you will see below exception in logs.

java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number. 

The exception occurs due to version mismatch. Room creates a table to store version in database as hash. Every time room opens database, it verifies version used in application with version stored in database. If it can’t verify, it will throw above exception crashing the application.

To fix the issue, you need to increase the version in code and provide Migration class. For example, if your SQLit API code uses version 1, then define RoomDatabase as version 2 like below example.

@Database(entities = {Coupon.class}, version = 2)
public abstract class CouponDatabase extends RoomDatabase {
    public abstract CouponDAO CouponDatabase();
}

If you run your app after changing the version, you will still get IllegalStateException. To fix this, you need to inform room what to do when version changes, meaning when database is upgraded, by providing Migration class.

Room Migration class is an abstract class with migrate() method which gets called when Room detects a version change. In the case of migrating to Room from SQLite API, since there are no changes to database tables, migrate method will be empty. Below is an example implementation of Migration. You can add migration class to RoomDatabase.Builder by calling addMigrations method on it as shown below.

Migration class

 static final Migration MIGRATION_1_1 = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
    }
}; 

Adding migration class to room database builder

 couponDatabase = Room.databaseBuilder(context,
                            CouponDatabase.class, "coupon db").addMigrations(MIGRATION_1_2).build();

If you don’t want existing data in database tables, you can inform room about recreating database by calling fallbackToDestructiveMigration method on RoomDatabase.Builder class. To get fallbackToDestructiveMigration behavior, you need to increase the version number and not provide Migration class.

Room Database Migration

If you are already using Room and you want to make changes to database tables, for example adding new column to a table, you can do that by increasing database version in your database class and providing Migrate class. Below Migration class example alters table.

 static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("ALTER TABLE person "
                + " ADD COLUMN skype TEXT");
    }
};