添加表格时房间迁移失败
Posted
技术标签:
【中文标题】添加表格时房间迁移失败【英文标题】:Room Migration Failed When Adding Table 【发布时间】:2022-01-22 12:56:24 【问题描述】:我正在尝试对我的数据库执行迁移。
我要添加的表如下:
@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()
我已确保Room Database Migration doesnt properly handle ALTER TABLE migration 中建议的预期和找到的表之间没有区别。事实上,我使用了文本检查器,唯一的区别是“PrimaryKeyPosition”,这在我刚才提到的链接中不是问题。
我不想破坏我以前的数据库,所以我避免使用 fallbackToDestructiveMigration()。无效和重新启动并没有消除错误。有没有其他人遇到过这个问题?
【问题讨论】:
我认为这个解决方案会帮助你github.com/orbitalsonic/… 【参考方案1】:RecipeOfDayDTO.image
,RecipeOfDayDTO.imageType
,RecipeOfDayDTO.instructions
是可以为空的String,所以你的迁移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`))")```
【讨论】:
感谢您的回复!我更改了它,但仍然缺少“PRIMARY KEY(id
)”,现在一切正常!【参考方案2】:
匹配期望和找到的方法是对带有@Entity
注释的类进行更改,确保该类被定义为@Database类的实体列表中的实体,然后编译(CTRL + F9) 然后检查生成的 java (通过 Android View)。
您查看同名但后缀为 _Impl 的类,该类使用 @Database 注释,并查看名为 createAllTables
的方法,该方法具有 Room 为每个表所期望的 SQL。然后,为新表复制相应的 SQL 就很简单了。对于其他更改,例如更改表,您可以根据生成的 java 中的 SQL 生成结果表/列。
例如将 RecipeOfDayDTO 添加到现有项目,然后将其添加到 @Database 类
导致在生成的 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 还支持自动迁移(可以处理添加表格而没有复杂性)。但是,它们依赖于 exportSchema 选项是否为真,并且之前和之后的版本都存在这样的模式。
见https://developer.android.com/training/data-storage/room/migrating-db-versions
【讨论】:
谢谢!对于未来的读者,要获取生成的 Java 文件,请单击您的数据库标题并按 CTRL + B 以查看该数据库的用法。正如@MikeT 提到的,它将以_Impl 为后缀,单击该Java 文件并将SQL 文本复制到您的迁移对象。以上是关于添加表格时房间迁移失败的主要内容,如果未能解决你的问题,请参考以下文章