添加 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.image
、RecipeOfDayDTO.imageType
、RecipeOfDayDTO.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
我正在尝试对我的数据库执行迁移。
我尝试添加的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()
我已确保
我不想破坏我以前的数据库,所以我避免使用 fallbackToDestructiveMigration()。无效和重新启动并没有消除错误。还有其他人遇到过这个问题吗?
RecipeOfDayDTO.image
、RecipeOfDayDTO.imageType
、RecipeOfDayDTO.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.
例如将 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