DEV Community

Cover image for Room Database Auto Migration
Boris Ochieng
Boris Ochieng

Posted on

11

Room Database Auto Migration

Introduction

Building offline-first Apps to enhance user experience during limited network connectivity is a common practice among developers. The Room Persistence Library, a part of the Android Architecture components, facilitates this by enabling local data storage. As the application scales, developers often encounter the need to fine-tune existing features or introduce new ones. When deploying these changes to end-users, it's crucial to preserve their existing on-device data. However, manual adjustments to the database schema can become cumbersome as the application evolves. This is where auto migration comes into play, automating the process and streamlining development workflows.

Setting up auto migration

To set up auto migration with Room, you'll first need to configure the Gradle Plugin to export the schema to a designated directory. In your project's top-level build.gradle file (/build.gradle.kts), declare the Room plugin and its version:

plugins {
id androidx.room' version '2.6.0' apply false
}
Enter fullscreen mode Exit fullscreen mode

Then, in the app-level build.gradle file (/app/build.gradle.kts), apply the plugin and specify the directory where the schema will be exported:

plugins {
id 'androidx.room'
}
room {
schemaDirectory "$projectDir/schemas"
}
Enter fullscreen mode Exit fullscreen mode

Ensure that the schema storage directory is located outside of your app directory. The $projectDir variable references the root directory of your project, and /schemas denotes the directory where the database file will be stored.

Next, set the exportSchema property to true within the @Database() annotation class. This step is essential as Room relies on the generated schema to execute migrations:

@Database( 
version = SampleDatabaseClass.LATEST_VERSION
entities = [Entity::class]
exportSchema = true
)
abstract class SampleDatabaseClass : RoomDatabase() {
companion object {
const val LATEST_VERSION = 1
}
...
}
Enter fullscreen mode Exit fullscreen mode

After completing these steps, rebuild your project to export the current database schema history into a JSON file.

Performing auto migration

To declare an automated migration between two database versions, specify the existing version and the new version. For instance, if the previous version was 1, and after making changes, the version is updated to 2, you can declare this migration in the database class:

@Database( 
version = SampleDatabaseClass.LATEST_VERSION,
entities = [Entity::class],
exportSchema = true,
autoMigrations = [
AutoMigration (from = 1, to = 2)
]
)
abstract class SampleDatabaseClass : RoomDatabase() {
companion object {
const val LATEST_VERSION = 2
}
...
}
Enter fullscreen mode Exit fullscreen mode

Rebuild your project to let Room handle the migration seamlessly. If further changes are made in subsequent versions, such as migrating from version 2 to 3, simply add the corresponding migration.

When you move to version 3 we will have to migrate from 2 to 3. We will simply add this to the class:

@Database( 
version = SampleDatabaseClass.LATEST_VERSION,
entities = [Entity::class],
exportSchema = true,
autoMigrations = [
AutoMigration (from = 1, to = 2),
AutoMigration (from = 2, to = 3)
]
)
abstract class SampleDatabaseClass : RoomDatabase() {
companion object {
const val LATEST_VERSION = 3
}
...
}
Enter fullscreen mode Exit fullscreen mode

Auto Migration Specifications

In some cases, Room may require additional information to perform migrations, particularly when changes involve deleting or renaming tables or columns. For such scenarios, you can use AutoMigrationSpec to provide the necessary details.

For example, if you need to rename a table, you can define an AutoMigrationSpec class within your database class and annotate it accordingly:

@Database( 
version = SampleDatabaseClass.LATEST_VERSION,
entities = [Entity::class],
exportSchema = true,
autoMigrations = [
AutoMigration (from = 1,
 to = 2, 
 spec = SampleDatabaseClass.YourAutoMigration::class),

]
)
abstract class SampleDatabaseClass : RoomDatabase() {
companion object {
const val LATEST_VERSION = 3
}

@RenameTable(fromTableName = "old_name", toTableName = "new_name")
class SampleAutoMigration : AutoMigrationSpec { }
...
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

The implementation of auto migration in Room significantly simplifies the process of managing database schema changes, enhancing the overall developer experience. By automating migration tasks, developers can focus more on building and refining app features without the burden of manual data management.

References

See it in action

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay