Android Room 数据库之数据库升级

本篇文章主要介绍数据库的自动迁移和手动迁移,属于数据库升级的简单入门,不涉及复杂的数据迁移;

一、自动迁移

自动迁移即表示不用写迁移相关代码,Room通过比对新旧表不同实现自动迁移;需要的配置如下:

1. app/library gradle 配置

gradle配置主要是添加room插件,用于生成新旧表比对所需的json

gradle.kts 复制代码
plugins {
    ...
    // androidx-room = { id = "androidx.room", version = "2.6.1" }
    alias(libs.plugins.androidx.room)
}

android {
    ...
    room {
        //指定json文件要生成的目录,如:app/schemas/数据库类对应的包名
        schemaDirectory("$projectDir/schemas")
    }
}

解释一下schemaDirectory("$projectDir/schemas")

  • projectDir就是模块的名称,比如是app模块则$projectDir/schemas等于app/schemas
  • 如果数据库类MyDatabase的报名是com.android.roomdemo.database.MyDatabase,那么生成的目录结构就是:app/schemas/com.android.roomdemo.database.MyDatabase/1.json,这里的1.json对应数据库的版本号version = 1

2. 数据库类配置

要支持自动迁移,必须设置exportSchema = true

kotlin 复制代码
@Database(entities = [Animal::class], version = 1, exportSchema = true)
abstract class MyDatabase : RoomDatabase() {
    abstract fun animalDao(): AnimalDao
}
新增表字段的情况

如下面这张表需要新增val belong: String字段

kotlin 复制代码
@Entity
data class Animal(val name: String, val age: Int, val sex: Int) {
    @PrimaryKey(autoGenerate = true) var id: Long = 0
}

Animal类改为

kotlin 复制代码
@Entity
data class Animal(val name: String, val age: Int, val sex: Int,
    @ColumnInfo(defaultValue = "")
    val belong: String,
) {
    @PrimaryKey(autoGenerate = true) var id: Long = 0
}

由于新增的belong是非null字符串,需要给默认值defaultValue = ""; MyDatabase修改如下,version+1,新增autoMigrations

kotlin 复制代码
@Database(entities = [Animal::class], version = 2, exportSchema = true, 
    autoMigrations = [AutoMigration(from = 1, to = 2)]
)
abstract class MyDatabase : RoomDatabase() {
    abstract fun animalDao(): AnimalDao
}

新增字段最简单,只需加autoMigrations = [AutoMigration(from = 1, to = 2)],该字段是个数据,如果是2升级3,再加一个AutoMigration(from = 2, to = 3)即可;

删除表字段的情况

如果涉及的是删除表字段@DeleteColumn、修改表字段名@RenameColumn、删除表@DeleteTable、修改表名@RenameTable,则需要用到AutoMigrationSpec;它们的使用方法都类似,这里以删除表字段为例, 如果要删除Animal表中的sex字段,首先需要创建类实现AutoMigrationSpec接口:

kotlin 复制代码
@DeleteColumn.Entries(
    DeleteColumn(tableName = "Animal", columnName = "sex")
)
class DeleteAutoMigrationSpec : AutoMigrationSpec {
}

然后在MyDatabase里设置spec = DeleteAutoMigrationSpec::class

kotlin 复制代码
@Database(
    entities = [Animal::class],
    version = 3, exportSchema = true, 
    autoMigrations = [
        AutoMigration(from = 1, to = 2),
        AutoMigration(
            from = 2,
            to = 3,
            spec = DeleteAutoMigrationSpec::class
        )
    ]
)
abstract class MyDatabase : RoomDatabase() {
    abstract fun animalDao(): AnimalDao
}

注意记得删除Animal类里的sex字段;到此,自动迁移适用于简单的数据修改。

手动数据迁移

手动数据迁移即通过自己写sql语句实现数据库升级,上面的MyDatabase类其实少了创建MyDatabase对象的方法,完整代码应该是这样:

kotlin 复制代码
@Database(
    entities = [Animal::class],
    version = 3, exportSchema = true, 
    autoMigrations = [
        AutoMigration(from = 1, to = 2),
        AutoMigration(
            from = 2,
            to = 3,
            spec = DeleteAutoMigrationSpec::class
        )
    ]
)
abstract class MyDatabase : RoomDatabase() {
    abstract fun animalDao(): AnimalDao
    
    companion object {

        @Volatile
        private var instance: MyDatabase? = null

        fun getInstance(context: Context): MyDatabase {
            return instance ?: synchronized(this) {
                instance ?: buildDatabase(context).also { instance = it }
            }
        }
        
        private fun buildDatabase(context: Context): MyDatabase {
            // 创建数据库对象
            return Room.databaseBuilder(context, MyDatabase::class.java, "my-db")
                .build()
        }
    }
}

关注创建数据库对象方法:

kotlin 复制代码
Room.databaseBuilder(context, MyDatabase::class.java, "my-db").build()

手动迁移只要在build方法前加上.addMigrations(migration)即可,如现在要在Animal表里加val isGirl: Boolean字段,首先在Animal里加上该字段:

kotlin 复制代码
@Entity
data class Animal(val name: String, val age: Int, val isGirl: Boolean) {
    @PrimaryKey(autoGenerate = true) var id: Long = 0
}

然后创建Migration对象:

kotlin 复制代码
val migration_3_4 = object : Migration(3, 4) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE Wong ADD COLUMN isGirl INTEGER NOT NULL DEFAULT 0")
    }
}

addMigrations:

kotlin 复制代码
Room.databaseBuilder(context, MyDatabase::class.java, "my-db")
.addMigrations(migration_3_4)
.build()

完!

相关推荐
GanGuaGua5 小时前
MySQL:表的约束
数据库·mysql
麋鹿原5 小时前
Android Room 数据库之简单上手
前端·kotlin
Li zlun6 小时前
MySQL 性能监控与安全管理完全指南
数据库·mysql·安全
养生技术人6 小时前
Oracle OCP认证考试题目详解082系列第48题
运维·数据库·sql·oracle·database·开闭原则·ocp
海阳宜家电脑7 小时前
Lazarus使用TSQLQuery更新的一点技巧
数据库·lazarus·tsqlquery
丨我是张先生丨7 小时前
SQLSERVER 查找存储过程中某个变量
数据库
感谢地心引力8 小时前
【Python】基于 PyQt6 和 Conda 的 PyInstaller 打包工具
数据库·python·conda·pyqt·pyinstaller
消失的旧时光-19438 小时前
Kotlin 判空写法对比与最佳实践
android·java·kotlin
lypzcgf9 小时前
Coze源码分析-资源库-编辑数据库-后端源码-数据存储层
数据库·coze·coze源码分析·智能体平台·ai应用平台