DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Room Database Migration: Auto and Manual Migration Strategies

As apps evolve, database schemas change. Learn Room migration, version management, and automated vs manual approaches.

Define Database Version

import androidx.room.Database
import androidx.room.RoomDatabase

@Database(
    entities = [User::class],
    version = 2  // Increment on schema change
)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}
Enter fullscreen mode Exit fullscreen mode

Manual Migration with SQL

val migration1to2 = object : Migration(1, 2) {
    override fun migrate(db: SupportSQLiteDatabase) {
        // Add new column
        db.execSQL("ALTER TABLE users ADD COLUMN email TEXT")
    }
}

val db = Room.databaseBuilder(context, AppDatabase::class.java, "app.db")
    .addMigrations(migration1to2)
    .build()
Enter fullscreen mode Exit fullscreen mode

Auto Migration (Room 2.4+)

@Database(
    entities = [User::class],
    version = 3,
    autoMigrations = [
        AutoMigration(from = 1, to = 2),
        AutoMigration(from = 2, to = 3)
    ]
)
abstract class AppDatabase : RoomDatabase()
Enter fullscreen mode Exit fullscreen mode

Modify Entity

// Version 1
@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String
)

// Version 2 - Add field with default
@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val email: String = ""  // Default for existing rows
)
Enter fullscreen mode Exit fullscreen mode

Complex Migration

val migration2to3 = object : Migration(2, 3) {
    override fun migrate(db: SupportSQLiteDatabase) {
        // Create new table with updated schema
        db.execSQL(
            """CREATE TABLE users_new (
                id INTEGER PRIMARY KEY,
                name TEXT,
                email TEXT,
                created_at INTEGER DEFAULT ${System.currentTimeMillis()}
            )"""
        )
        // Copy data
        db.execSQL("INSERT INTO users_new SELECT id, name, email, 0 FROM users")
        // Drop old table
        db.execSQL("DROP TABLE users")
        // Rename new table
        db.execSQL("ALTER TABLE users_new RENAME TO users")
    }
}
Enter fullscreen mode Exit fullscreen mode

Test migrations on production data backup. Always increment version before rollout. AutoMigration works only for simple schema changes.


8 Android app templates (Habit Tracker, Budget Manager, Task Manager, and more) available on Gumroad

Top comments (0)