当在更新项目过程中遇到新增数据库字段,此时需同步数据库操作,更改目标类:
@Database(entities = [Bean::class], version = 1, exportSchema = false)
@TypeConverters(DateAdapters::class)
abstract class AppDatabase : RoomDatabase() {
companion object {
private const val TAG = "AppDatabase"
private const val DATABASE_NAME = "mvvm_database"
fun initialize(@ApplicationContext context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
.apply {
fallbackToDestructiveMigration()
}.build()
}
}
abstract fun beanDao(): BeanDao
}
#1. 简单粗暴的操作:对于更新数据库操作,直接更改版本号:version (大于原来的值即可,+1即可):
@Database(entities = [Bean::class], version = 2, exportSchema = false)
⚠️ 如果没有提供足够的迁移来从当前版本移动到最新版本,Room 将清除数据库并重新创建。对于 #1,因为仅仅更新了版本号升级,所以Room会把本地的数据库清除并创建,即本地数据库的数据将会丢失,这并不是推荐的操作。
#2. 基于 #1 的更改,继续为数据库创建迁移脚本 addMigrations() ,在表级别进行适当的更改以支持同步数据库字段新增:
@Database(entities = [Bean::class], version = 2, exportSchema = false)
@TypeConverters(DateAdapters::class)
abstract class AppDatabase : RoomDatabase() {
companion object {
private const val DATABASE_NAME = "mvvm_database"
fun initialize(@ApplicationContext context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
.apply {
fallbackToDestructiveMigration()
addMigrations(
MIGRATION_1_2
)
}.build()
}
// 如果数据库有改动,则需要更新数据库版本来同步更新数据库,以下为示例方法:
private val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Bean ADD COLUMN `deletedDate` INTEGER")
database.execSQL("ALTER TABLE Bean ADD COLUMN `isDeleted` INTEGER NOT NULL DEFAULT 0")
}
}
}
abstract fun beanDao(): BeanDao
}
⚠️ Room会根据提供的迁移脚本Migration来从当前版本移动到最新版本,Room 并不会清除数据库并重新创建。
ADD COLUMN还需要注意一点在非空字段的时候:
Android Room- 为表新增非空字段时报错
* 补充:如果只对当前表进行字段更新,又对本地数据没有什么要求,我们可以先删除相应的表,再创建新表:(这适用于所有的表字段更新)
private val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE IF EXISTS Bean")
database.execSQL("CREATE TABLE IF NOT EXISTS `Bean` (`id` INTEGER NOT NULL, `checksum` TEXT NOT NULL, `deletedDate` INTEGER, `isDeleted` INTEGER NOT NULL, PRIMARY KEY(`id`))")
}
}