Room确实NOT有一个好的迁移系统,至少要到2.1.0-alpha03
.
因此,在我们拥有更好的迁移系统之前,有一些解决方案可以让您在房间中轻松migrations.
由于没有像@Database(createNewTables = true)
或MigrationSystem.createTable(User::class)
这样的方法,应该有这样或那样的方法,所以唯一可能的方法是运行
CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))
在你的migrate
方法里面.
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))")
}
}
为了达到SQL以上的脚本,你有4种方法
1.自己写
基本上,您必须编写与Room生成的脚本相匹配的上面的脚本.这条路是可能的,不可行的.(假设您有50个字段)
2.导出模式
如果在@Database
注释中包含exportSchema = true
,文件室将在项目文件夹的/schemas中生成数据库模式.用法是
@Database(entities = [User::class], version = 2, exportSchema = true)
abstract class AppDatabase : RoomDatabase {
//...
}
确保在应用程序模块的build.grade
行中包含以下行
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
当您运行或构建项目时,您将获得一个JSON文件2.json
,其中包含您的Room数据库中的所有查询.
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "325bd539353db508c5248423a1c88c03",
"entities": [
{
"tableName": "User",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
因此,您可以在migrate
方法中包含以上createSql
项.
3.从AppDatabase_Impl获取查询
如果您不想导出模式,您仍然可以通过运行或构建将生成AppDatabase_Impl.java
个文件的项目来获取查询.并且在指定的文件中可以有.
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))");
在createAllTables
方法中,将有所有实体的创建脚本.你可以得到它并将其包含在你的migrate
方法中.
4.注释处理.
正如您可能猜到的,Room会在编译时间内生成上述schema
个和AppDatabase_Impl
个文件,并使用您添加的注释处理
kapt "androidx.room:room-compiler:$room_version"
这意味着您也可以这样做,并创建自己的注释处理库,为您生成所有必要的create查询.
我们的 idea 是为@Entity
和@Database
的房间注释创建一个注释处理库.以一个用@Entity
注释的类为例.以下是您必须遵循的步骤
- 创建一个新的
StringBuilder
并附加"如果不存在创建表"
- 从
class.simplename
或@Entity
的tableName
字段中获取表名.把它加到你的StringBuilder
- 然后为类的每个字段创建SQL列.通过字段本身或
@ColumnInfo
注释获取字段的名称、类型和可空性.
- 将主键加
@PrimaryKey
- 如果存在,则添加
ForeignKey
和Indices
.
- 完成后,将其转换为字符串,并将其保存在您想要使用的某个新类中.例如,按如下方式保存它
public final class UserSqlUtils {
public String createTable = "CREATE TABLE IF NOT EXISTS User (id INTEGER, PRIMARY KEY(id))";
}
然后,你可以把它当作
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(UserSqlUtils().createTable)
}
}
我为自己制作了这样一个库,你可以查看,甚至可以在你的项目中使用它.请注意,我创建的库没有满,它只满足了我创建表的要求.
RoomExtension for better Migration
Application that uses RoomExtension
希望它能派上用场.
使现代化
在 compose 本文时,房间版本是2.1.0-alpha03
,当我给开发人员发邮箱时,我得到的回复是
预计在2.2.0
年内将有更好的迁移系统
不幸的是,我们仍然缺乏更好的移民体系.