Room DB: Advanced Data Persistence

This tutorial introduces more advanced concepts for use with the Room persistence library, such as migration and indexing. By Lance Gleason.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Index Drawbacks

While indexes can be very helpful, there are some drawbacks to be aware of. One big drawback stems from the need to add a record to another data structure, which means inserts into a table with an index may take longer to perform. Another drawback is that indexes increase the amount of storage needed by the database.

Reads or inserts

Some scenarios where an index to common query fields may be beneficial:

  • You read data from a table more often than you write to it.
  • Query speed is more important than insert speed.

Updating Tests

Since you made changes to your code, you might want to re-run your unit tests to make sure that you haven’t broken anything. Run them and you will see the following:

Failing tests

Oops! This is happening because you are instantiating your own version of the migrated Room database in your getMigratedRoomDatabase() method in ListItemMigrationTest. Currently, it is only migrating your database to version 2, but Room will not work unless your database is migrated to the current version, which is 3.

To fix this, add .addMigrations(AppDatabase.MIGRATION_2_TO_3) after the .addMigrations(AppDatabase.MIGRATION_1_TO_2) in getMigratedRoomDatabase(). Your method will now look like this:

  private fun getMigratedRoomDatabase(): AppDatabase {
    //1
    val appDatabase = Room.databaseBuilder(
        InstrumentationRegistry.getTargetContext(),
        AppDatabase::class.java, TEST_DB_NAME)
        //2
        .addMigrations(AppDatabase.MIGRATION_1_TO_2)
        .addMigrations(AppDatabase.MIGRATION_2_TO_3)
        //3
        .build()
    //4
    migrationTestHelperRule.closeWhenFinished(appDatabase)
    return appDatabase
  }

Since your tests are now testing version 3 of your migration instead of version 2, rename the existing tests from the following,

@Test
fun migrating_from_1_to_2_retains_version_1_data() {
  ...
}

@Test
fun inserting_a_record_into_list_items_after_migrating_from_1_to_2_succeeds() {
  ...
}

to:

@Test
fun migrating_from_1_to_3_retains_version_1_data() {
  ...
}

@Test
fun inserting_a_record_into_list_items_after_migrating_from_1_to_3_succeeds() {
  ...
}

Because the index does not affect the structure of your data or how you access it, you do not need change any other code.

Now, run your tests and all of them will pass!

Passing tests

Where to Go From Here?

You can download the final project using the Download materials button at the top or bottom of this tutorial.

As you start to work with more complex data, you can use Type Converters to map database types to your own custom types. If you are new to data persistence on Android and want more background, you can check out the Saving Data on Android video course, which covers Shared Preferences, saving to files, SQLite and migrations.

As a challenge, you can also try to:

  • Add the ability to delete a list item.
  • Create an onClick event for each list item that allows you to edit the item and save the update to your database.

Feel free to share your feedback or findings, and please post your questions in the comments section below or in the forums. I hope that you’ve enjoyed this tutorial on advanced data persistence with Room!