15

问题

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

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

原始内容模型

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

新内容模型

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

尝试的解决方案

在阅读了 Google Developer Advocate 的解释Understanding migrations with Room后,我尝试了她在帖子部分Migrations with complex schema changes中概述的解决方案,这需要复制原始表,删除旧表,然后重命名新创建的表。

使用下面的方法,此行会出现运行时错误: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");
  }
};
4

2 回答 2

16

解决方案

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

一旦 Android 升级了一个这样的命令来改变一个表列,就可以了:database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount")

于 2018-10-07T03:56:07.130 回答
9

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

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

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

于 2018-10-05T07:01:12.640 回答