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

完!

相关推荐
Maỿbe18 小时前
Redis的持久化
数据库·redis·缓存
用户693717500138419 小时前
Kotlin 全量关键字全面整理,并附上简洁示例,确保每一个关键字都清楚易懂。
kotlin
努力学习的小廉19 小时前
初识MYSQL —— 基本查询
数据库·mysql·1024程序员节
许泽宇的技术分享19 小时前
让数据库“听懂“人话:Text2Sql.Net 深度技术解析
数据库·.net
珊珊而川20 小时前
MAC-SQL 算法一
数据库·sql·oracle
听风吟丶21 小时前
深入解析 Spring Boot 自动配置:原理、实践与进阶
java·数据库·sql
风语者日志21 小时前
[LitCTF 2023]这是什么?SQL !注一下 !
android·数据库·sql
lang2015092821 小时前
Spring Boot 核心技巧与实战指南
java·数据库·spring boot
呆呆小金人1 天前
SQL视图:虚拟表的完整指南
大数据·数据库·数据仓库·sql·数据库开发·etl·etl工程师
笨手笨脚の1 天前
Mysql 读书笔记
数据库·mysql·事务·索引·orderby·自增主键