Android Room:如何迁移列重命名?

Ada*_*itz 5 sql android android-sqlite android-room

问题

我的应用崩溃了,因为我没有正确处理迁移。我正在寻找一种迁移表中1列名称的解决方案。

在我的项目中,我有一个名为“ content ” 的房间表,其双人间属性为“ archivedCount ”。在该应用程序的最新版本中,属性archivedCount属性重命名为dismissCount,仍为Double类型

原始内容模型

@Entity(tableName = "content")
data class Content(@PrimaryKey var id: String, var archiveCount: Double) : Parcelable {...}
Run Code Online (Sandbox Code Playgroud)

新内容模型

@Entity(tableName = "content")
data class Content(@PrimaryKey var id: String, var dismissCount: Double) : Parcelable {...}
Run Code Online (Sandbox Code Playgroud)

尝试的解决方案

阅读了Google Developer Advocate的解释《用Room进行迁移》后,我尝试了在文章的“ 使用复杂的模式进行迁移 ”一节中概述的解决方案,该过程包括复制原始表,删除旧表,然后重命名新创建的表。

使用下面的以下方法,在此行上会出现运行时错误:database.execSQL("INSERT INTO content_new (id, dismissCount) SELECT id, archiveCount FROM users");因为我已经清除了应用程序的缓存,所以旧表不再存在。

是否可以在不重新创建整个表的情况下更新单个列?

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
    // Create the new table
    database.execSQL(
            "CREATE TABLE content_new (id TEXT, dismissCount REAL, PRIMARY KEY(id))");
    // Copy the data
    database.execSQL("INSERT INTO content_new (id, dismissCount) SELECT id, archiveCount FROM users");
    // Remove the old table
    database.execSQL("DROP TABLE content");
    // Change the table name to the correct one
    database.execSQL("ALTER TABLE content_new RENAME TO content");
  }
};
Run Code Online (Sandbox Code Playgroud)

ata*_*nko 8

有一个没有迁移的解决方案 - 使用ColumnInfo

data class Content(@PrimaryKey var id: String,  @ColumnInfo(name = "archiveCount") var dismissCount: Double) : Parcelable{...}
Run Code Online (Sandbox Code Playgroud)

数据库列仍为archiveCount,但在 Kotlin 中的属性将被重命名。

  • 谢谢@atarasenki,这是一个很好的解决方法。然而,它并没有解决问题的根源,更像是一种“创可贴”式的解决方案。 (6认同)

Ada*_*itz 5

感谢@TimBiegeleisen的指导,我们发现针对API 2728 的SQLite 3.19Android实现尚未升级到版本3.25 SQLite,该功能允许在此StackOverflow帖子中概述

Android升级后,将可以使用诸如此类的命令来更改表格列: database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount")

  • SQLite 中还没有吗?我写了这个:database.execSQL("ALTER TABLE Expense RENAME COLUMN Price TO amount"); 编译时出现错误 android.database.sqlite.SQLiteException: 近“COLUMN”: 语法错误 (代码 1 SQLITE_ERROR): : ALTER TABLE Expense RENAME COLUMN Price TO amount 而且我还得到了该行的提示: Got COLUMN, Expected TO (8认同)
  • 确实需要注意的是,这不适用于不使用 SQLite 3.25 的 Android 设备,在发表此评论时,这些设备都是 **ALL**,因此截至 2020 年 11 月 11 日,此答案不正确。我找到的唯一解决方案是使用逻辑创建一个新表,复制数据,删除旧表,然后重命名新表。 (3认同)