本篇文章主要介绍数据库的自动迁移和手动迁移,属于数据库升级的简单入门,不涉及复杂的数据迁移;
一、自动迁移
自动迁移即表示不用写迁移相关代码,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()
完!