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
}
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()
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()
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
)
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")
}
}
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)