添加 Table 时房间迁移失败

Room Migration Failed When Adding Table

我正在尝试对我的数据库执行迁移。

我尝试添加的table如下:

@Entity(tableName = "Recipe_Of_Day_Entity")
data class RecipeOfDayDTO(
    @PrimaryKey
    @ColumnInfo(name = "id")
    val id : String = UUID.randomUUID().toString(),
    @ColumnInfo(name = "vegetarian")
    val vegetarian: Boolean,
    @ColumnInfo(name = "vegan")
    val vegan: Boolean,
    @ColumnInfo(name = "glutenFree")
    val glutenFree: Boolean,
    @ColumnInfo(name = "dairyFree")
    val dairyFree: Boolean,
    @ColumnInfo(name = "veryHealthy")
    val veryHealthy: Boolean,
    @ColumnInfo(name = "image")
    val image: String?,
    @ColumnInfo(name = "imageType")
    val imageType: String?,
    @ColumnInfo(name = "instructions")
    val instructions: String?) 

迁移对象定义如下:

val MIGRATION_4_5: Migration = object : Migration(4, 5) {
    override fun migrate(database: SupportSQLiteDatabase) {
        // https://developer.android.com/reference/android/arch/persistence/room/ColumnInfo
        database.execSQL("CREATE TABLE IF NOT EXISTS `RecipeOfDayDTO` (`id` TEXT NOT NULL, `vegetarian` " +
                "INTEGER NOT NULL, `vegan` INTEGER NOT NULL, `glutenFree` INTEGER NOT NULL, `dairyFree` INTEGER NOT NULL," +
                "`veryHealthy` INTEGER NOT NULL, `image` TEXT NOT NULL, `imageType` TEXT NOT NULL, `instructions` TEXT NOT NULL)")
    }
}

我正在建立如下数据库:

@Database(entities = [IngredientDataClassDTO::class, RecipeNotificationClassDTO::class, RecipeOfDayDTO::class], version = 5, exportSchema = true)
abstract class IngredientDatabase : RoomDatabase() {
.
.
.
Room.databaseBuilder(
                        context.applicationContext,
                        IngredientDatabase::class.java,
                        "saved_ingredient_database"
                    )
           
                        // https://medium.com/androiddevelopers/understanding-migrations-with-room-f01e04b07929
                        .addMigrations(MIGRATION_4_5)
                        .build()

我已确保 中建议的预期 table 与发现的 table 之间没有差异。事实上,我使用了文本检查器,唯一的区别是“PrimaryKeyPosition”,这在我刚才提到的 link 中不是问题。

我不想破坏我以前的数据库,所以我避免使用 fallbackToDestructiveMigration()。无效和重新启动并没有消除错误。还有其他人遇到过这个问题吗?

RecipeOfDayDTO.imageRecipeOfDayDTO.imageTypeRecipeOfDayDTO.instructions是可空字符串,所以你的迁移SQL一定是这样的;

database.execSQL("CREATE TABLE IF NOT EXISTS `RecipeOfDayDTO` (`id` TEXT NOT NULL, `vegetarian` " +
                "INTEGER NOT NULL, `vegan` INTEGER NOT NULL, `glutenFree` INTEGER NOT NULL, `dairyFree` INTEGER NOT NULL," +
                "`veryHealthy` INTEGER NOT NULL, `image` TEXT NULL, `imageType` TEXT NULL, `instructions` TEXT NULL, PRIMARY KEY(`id`))")```

匹配expected和found的方法是对注释为@Entity的class(es)进行修改,确保class被定义为实体@Database class 的实体列表,然后编译 (CTRL + F9) 然后检查生成的 java(通过 Android 查看)。

你看一下 class 是他同名但后缀为 _Impl 的 class 用 @Database 注释和名为 createAllTables 的方法具有 SQL Room 期望每个 table。然后为新的 table(s) 复制相应的 SQL 是一件简单的事情。对于其他更改,例如更改 table,您可以将生成的 table(s)/列基于生成的 java.

中的 SQL

例如将 RecipeOfDayDTO 添加到现有项目,然后将其添加到 @Database class

导致在生成的 java 中找到以下方法:-

  @Override
  public void createAllTables(SupportSQLiteDatabase _db) {
    _db.execSQL("CREATE TABLE IF NOT EXISTS `NoteEntity` (`id` INTEGER, `startRef` INTEGER NOT NULL, `endRef` INTEGER NOT NULL, `content` TEXT NOT NULL, PRIMARY KEY(`id`))");
    _db.execSQL("CREATE TABLE IF NOT EXISTS `Recipe_Of_Day_Entity` (`id` TEXT NOT NULL, `vegetarian` INTEGER NOT NULL, `vegan` INTEGER NOT NULL, `glutenFree` INTEGER NOT NULL, `dairyFree` INTEGER NOT NULL, `veryHealthy` INTEGER NOT NULL, `image` TEXT, `imageType` TEXT, `instructions` TEXT, PRIMARY KEY(`id`))");
    _db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
    _db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c8707866be882430083eee62243a71ed')");
  }

所以只需复制 SQL :-

"CREATE TABLE IF NOT EXISTS `Recipe_Of_Day_Entity` (`id` TEXT NOT NULL, `vegetarian` INTEGER NOT NULL, `vegan` INTEGER NOT NULL, `glutenFree` INTEGER NOT NULL, `dairyFree` INTEGER NOT NULL, `veryHealthy` INTEGER NOT NULL, `image` TEXT, `imageType` TEXT, `instructions` TEXT, PRIMARY KEY(`id`))"

进入迁移,无需花时间试图确定什么匹配和不匹配。

在 2.4.0-aplh01 及更高版本中,Room 还支持自动迁移(这将处理添加 table 而不复杂)。但是,他们依赖于 exportSchema 选项为真,并且这样的架构存在于之前和之后的版本中。

https://developer.android.com/training/data-storage/room/migrating-db-versions