DEV Community

Cover image for Room Database Auto Migration
Boris Ochieng
Boris Ochieng

Posted on

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

Top comments (0)