如果只添加新表,房间数据库迁移

新手上路,请多包涵

假设我有一个简单的 Room 数据库:

 @Database(entities = {User.class}, version = 1)
abstract class AppDatabase extends RoomDatabase {
    public abstract Dao getDao();
}

现在,我要添加一个新实体: Pet 并将版本升级到 2:

 @Database(entities = {User.class, Pet.class}, version = 2)
abstract class AppDatabase extends RoomDatabase {
    public abstract Dao getDao();
}

当然,Room 抛出异常: java.lang.IllegalStateException: A migration from 1 to 2 is necessary.

假设,我没有更改 User 类(因此所有数据都是安全的),我必须提供只创建一个新表的迁移。因此,我正在研究 Room 生成的类,搜索生成的查询以创建我的新表,将其复制并粘贴到迁移中:

 final Migration MIGRATION_1_2 =
        new Migration(1, 2) {
            @Override
            public void migrate(@NonNull final SupportSQLiteDatabase database) {
                database.execSQL("CREATE TABLE IF NOT EXISTS `Pet` (`name` TEXT NOT NULL, PRIMARY KEY(`name`))");
            }
        };

但是我发现手动操作不方便。有没有办法告诉 Room: 我没有触及任何现有表格,因此数据是安全的。请为我创建迁移?

原文由 Piotr Aleksander Chmielowski 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 329
2 个回答

Room 没有 一个好的迁移系统,至少在 2.1.0-alpha03 之前没有。

因此,在我们拥有更好的迁移系统之前,有一些解决方法可以在房间内轻松迁移。

由于没有 @Database(createNewTables = true)MigrationSystem.createTable(User::class) 这样的方法,应该有一个或另一个,唯一可能的方法是运行

CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))

在你的 migrate 方法中。

 val MIGRATION_1_2 = object : Migration(1, 2){
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))")
    }
}

为了得到上面的 SQL 脚本,你有 4 种方法

1.自己写

基本上,您必须编写与 Room 生成的脚本相匹配的上述脚本。这种方式是可行的,不可行的。 (假设你有 50 个字段)

2.导出模式

如果您在 --- 注释中包含 exportSchema = true @Database 注释,Room 将在项目文件夹的 /schemas 中生成数据库架构。用法是

@Database(entities = [User::class], version = 2, exportSchema = true)
abstract class AppDatabase : RoomDatabase {
   //...
}

确保您已在应用程序模块的 build.grade 中包含以下行

kapt {
    arguments {
        arg("room.schemaLocation", "$projectDir/schemas".toString())
    }
}

当您运行或构建项目时,您将获得一个 JSON 文件 2.json ,其中包含您的 Room 数据库中的所有查询。

   "formatVersion": 1,
  "database": {
    "version": 2,
    "identityHash": "325bd539353db508c5248423a1c88c03",
    "entities": [
      {
        "tableName": "User",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
        "fields": [
          {
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER",
            "notNull": true
          },

因此,您可以在 --- 方法中包含上面的 createSql migrate 方法。

3.从AppDatabase_Impl获取查询

如果您不想导出架构,您仍然可以通过运行或构建将生成 AppDatabase_Impl.java 文件的项目来获取查询。并在您可以拥有的指定文件中。

 @Override
public void createAllTables(SupportSQLiteDatabase _db) {
  _db.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))");

createAllTables 方法中,将有所有实体的创建脚本。您可以获得它并将其包含在您的 migrate 方法中。

4.注解处理。

正如您可能猜到的那样,Room 会在编译时间内生成上述所有 schemaAppDatabase_Impl 文件,并使用您添加的注释处理

kapt "androidx.room:room-compiler:$room_version"

这意味着您也可以做同样的事情并制作自己的注释处理库,为您生成所有必要的创建查询。

这个想法是为 @Entity@Database 的房间注释制作一个注释处理库。以注解为 @Entity 的类为例。这些是您必须遵循的步骤

  1. 创建一个新的 StringBuilder 并附加“如果不存在则创建表”
  2. class.simplename 或通过 tableName 的字段 @Entity 获取表名。将它添加到您的 StringBuilder
  3. 然后为类的每个字段创建 SQL 列。通过字段本身或 @ColumnInfo 注释获取字段的名称、类型、可空性。对于每个字段,您必须将 id INTEGER NOT NULL 添加到您的列样式 StringBuilder
  4. 添加主键 @PrimaryKey
  5. 添加 ForeignKeyIndices 如果存在。
  6. 完成后将其转换为字符串并将其保存在您要使用的一些新类中。比如像下面这样保存
public final class UserSqlUtils {
  public String createTable = "CREATE TABLE IF NOT EXISTS User (id INTEGER, PRIMARY KEY(id))";
}

然后,您可以将其用作

val MIGRATION_1_2 = object : Migration(1, 2){
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL(UserSqlUtils().createTable)
    }
}

我为自己制作了这样一个库,您可以查看它,甚至可以在您的项目中使用它。请注意,我创建的库并不完整,它只是满足我创建表的要求。

用于更好迁移的 RoomExtension

使用 RoomExtension 的应用程序

希望它有用。

更新

在撰写此答案时,房间版本为 2.1.0-alpha03 当我向开发人员发送电子邮件时,我收到了回复

预计会有更好的迁移系统 2.2.0

不幸的是,我们仍然缺乏更好的迁移系统。

原文由 musooff 发布,翻译遵循 CC BY-SA 4.0 许可协议

抱歉,Room 不支持在不丢失数据的情况下自动创建表。

必须编写迁移。否则,它将擦除所有数据并创建新的表结构。

原文由 Viswanath Kumar Sandu 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题