移动在房间与Android数组的字符串



我有一个Android数据库与房间,我已经删除了一列。我正在进行迁移,我发现这并不像对已删除的列执行DROP操作那么简单。

然后我看到我必须采取一系列步骤,创建一个临时表,这个临时表稍后将成为删除列的新表,但问题是这个表包含一个字段,这是一个字符串数组,我不知道如何在SQL中声明

@Entity(tableName = "recipe_table")
data class RecipesDb(
@PrimaryKey
@ColumnInfo(name = "id")
val id: Long,
@ColumnInfo(name = "name")
val name: String,
@ColumnInfo(name = "category")
val category: List<String>,
@ColumnInfo(name = "isRecommended")
val isRecommended: Boolean,
@ColumnInfo(name = "images")
val images: List<String>,
@ColumnInfo(name = "ingredients")
val ingredients: List<String>,
@ColumnInfo(name = "date")
val date: Long,
@ColumnInfo(name = "time")
val time: Int,
@ColumnInfo(name = "difficult")
val difficult: String,
@ColumnInfo(name = "originalUrl")
val originalURL: String? = null,
@ColumnInfo(name = "author")
val author: String,
@ColumnInfo(name = "siteName")
val siteName: String
)

现在我已经删除了ingredients列。我想做这样的事情:

private val MIGRATION_3_2 = object : Migration(3,2) {
override fun migrate(database: SupportSQLiteDatabase) {
//Drop column isn't supported by SQLite, so the data must manually be moved
with(database) {
execSQL("CREATE TABLE Users_Backup (id INTEGER, name TEXT, PRIMARY KEY (id))")
execSQL("INSERT INTO Users_Backup SELECT id, name FROM Users")
execSQL("DROP TABLE Users")
execSQL("ALTER TABLE Users_Backup RENAME to Users")
}
}
}

但是当我声明新的临时表User_Backup时,我不知道如何指定其中一个字段是Array。最后,我能够做到这一点与房间的自动化和创建界面,但我想知道如何做到这一点,以及这种方式。

简单的方法是在@Database注释的实体列表中使用更改后的@Entity注释类编译代码(Ctrl+F9)。

然后查看生成的java(通过Android Studio中的Android View可见)。将有一个与@Database注释类名称相同的类,但后缀为_Impl.

在这个类中将有一个方法命名为createAllTables,这包括room用于创建表的SQL。

只需复制并粘贴适当的SQL,然后更改表名,这不仅将使用正确的类型,还将应用Room期望的正确列约束。

我建议

  1. 在创建表之前添加execSQL("DROP TABLE IF EXISTS the_backup_table_name;")(以防它已经存在)
  2. execSQL("DROP TABLE IF EXISTS the_original_table_name")代替execSQL("DROP TABLE Users")
  • 就我个人而言,我总是重命名原表的表名,然后重命名新表,然后最后删除重命名的原表。

我会使用:-

private val MIGRATION_3_2 = object : Migration(3,2) {
override fun migrate(database: SupportSQLiteDatabase) {
//Drop column isn't supported by SQLite, so the data must manually be moved
with(database) {
execSQL("DROP TABLE IF EXISTS Users_Backup")
execSQL("CREATE TABLE IF NOT EXISTS ....) //<<<<< SEE NOTES BELOW, the SQL MUST BE CHANGED.
execSQL("INSERT INTO Users_Backup SELECT id, name FROM Users")
execSQL("ALTER TABLE Users RENAME TO Old_Users")
execSQL("ALTER TABLE Users_Backup RENAME to Users")
execSQL("DROP TABLE IF EXISTS Old_users")
}
}
}
  • 注意…表示SQL是从生成的java中复制的,并且表名从Users更改到Users_Backup
  • 第一行将删除users_backup,以防它碰巧存在,它只是在不寻常的情况下不太可能失败。
  • 而不是删除UsersUsers_Backup的RENAME前的表用户到。第4个execSQL修改了Users的名称。如果在修改Users_Backup时出现问题Users
  • 当所有操作完成后,原来的Users表(现在名为Old_Users)将被删除。
  • 这些都是更安全的。

最新更新