在 Kotlin 中向数据 class 添加新字段时如何处理更改

How to deal with changes when adding new field to a data class in Kotlin

我有这个数据class:

data class User(
  val name:String,
  val age: Int
)

我用这个在我的数据库中保存了用户的数据,现在的问题是我想添加一个新字段

val gender: String

如果我添加这个,应用程序在从数据库中检索用户数据时崩溃,因为它不再是相同的数据。

这是我从数据库中检索数据的代码:

@Query("SELECT*FROM users WHERE name =:name")
suspend fun getUser(name:String):Flow<User>

如果可能的话,我最想看到伪代码解决方案。

您需要迁移数据库。您可以在 Migrating Room databases.

找到所有相关说明

如果您的房间版本是 2.4.0-alpha01 或更高版本:

在你的数据库中替换:

@Database(
  version = 1,
  entities = {User.class}
)

与:

@Database(
  version = 2,
  entities = {User.class},
  autoMigrations = {
    @AutoMigration (from = 1, to = 2)
  }
)

否则您将需要手动进行迁移:

将此添加到您的数据库class:

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
  @Override
  public void migrate(SupportSQLiteDatabase database) {
    database.execSQL("ALTER TABLE users "
      + " ADD COLUMN gender TEXT");
  }
};

并将 .addMigrations(MIGRATION_1_2) 添加到您的 Room.databaseBuilder()

你有两种解决方案,正确的一种和快速的一种:

正确的:

@Database(
     version = 2,
     entities = [User::class],
     autoMigrations = [
         AutoMigration (from = 1, to = 2)
     ]
)

代码取自:https://developer.android.com/training/data-storage/room/migrating-db-versions#automated

这是一个迁移,因为在这种特殊情况下,您只是向 table 添加一列,您可以尝试这种方法,它很可能会奏效。如果没有,那么您必须使用一些 SQL 代码实施您自己的迁移。

快的那个:

无论您在何处创建数据库,都请添加以下方法:.fallbackToDestructiveMigration() 。这将使每当您的数据库版本发生变化并且需要迁移并且未提供时,它只会删除旧数据库并重新创建它。考虑到此解决方案会清除您之前保存的所有信息,因此请仅在您赶时间并且不关心在更新之间维护数据时才尝试使用它。