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

完!

相关推荐
韩立学长2 分钟前
基于Springboot泉州旅游攻略平台d5h5zz02(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·旅游
Re.不晚38 分钟前
MySQL进阶之战——索引、事务与锁、高可用架构的三重奏
数据库·mysql·架构
老邓计算机毕设1 小时前
SSM智慧社区信息化服务平台4v5hv(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·智慧社区、·信息化平台
麦聪聊数据1 小时前
为何通用堡垒机无法在数据库运维中实现精准风控?
数据库·sql·安全·低代码·架构
2301_790300961 小时前
Python数据库操作:SQLAlchemy ORM指南
jvm·数据库·python
m0_736919101 小时前
用Pandas处理时间序列数据(Time Series)
jvm·数据库·python
亓才孓1 小时前
[JDBC]PreparedStatement替代Statement
java·数据库
m0_466525292 小时前
绿盟科技风云卫AI安全能力平台成果重磅发布
大数据·数据库·人工智能·安全
爱学习的阿磊3 小时前
使用Fabric自动化你的部署流程
jvm·数据库·python
枷锁—sha3 小时前
【SRC】SQL注入快速判定与应对策略(一)
网络·数据库·sql·安全·网络安全·系统安全