关于android:Room-中的数据库自动迁移功能

59次阅读

共计 2986 个字符,预计需要花费 8 分钟才能阅读完成。

在不同 Room 之间轻松挪动数据库表

2.4.0-alpha01 版本开始,Room 库里新退出了主动迁徙的性能,这让数据库迁徙的实现变得更简略。以往每当您的数据库 schema 发生变化时,您都必须实现一个 Migration 类,并将理论变动告知 Room,且少数状况下均波及编写和执行简单的 SQL 查问。

当初,应用主动迁徙性能,您就能够指定从哪个版本迁徙到哪个版本了。Room 能够针对简略的状况主动生成迁徙程序,例如增加或删除列、创立新的数据库表。然而在不置可否的场景下,Room 则须要一些帮忙。您能够提供具体的标准——比方重命名或删除列 / 数据库表——基于此,Room 将为您生成并运行迁徙动作。接下来让咱们一起看一些例子,以及具体的运行体现吧!

在主动迁徙中退出主动元素

举例来说,咱们须要在数据库中的一个表中新增加一列,并将数据库从版本 1 降级到版本 2。那么咱们就须要更新 @Database 注解为其递增版本号,并增加从版本 1 到 2 的主动迁徙:

/* Copyright 2020 Google LLC.  
   SPDX-License-Identifier: Apache-2.0 */

@Database(
-   version = 1,
+   version = 2,
    entities = [Doggos.class],
+   autoMigrations = [+         AutoMigration (from = 1, to = 2)
+     ]
  )
abstract class DoggosDatabase : RoomDatabase {}

每当数据库版本再次扭转时,您只需更新 autoMigrations 列表,增加一个新的:

/* Copyright 2020 Google LLC.  
   SPDX-License-Identifier: Apache-2.0 */

@Database(
-   version = 2,
+   version = 3,
    entities = [Doggos.class],
    autoMigrations = [AutoMigration (from = 1, to = 2),
+      AutoMigration (from = 2, to = 3)
     ]
  )
abstract class DoggosDatabase : RoomDatabase {}

针对在 @Database schema 中申明的实体,如增加新列或表,更新主键、外键或索引,或更改列的默认值,Room 会自动检测出这些变动,不须要额定染指。

⚠️请留神: 从实现层面来说,Room 的主动迁徙依赖于所生成的数据库 schema,因而在应用 autoMigrations 时,请确保 @Database 中的 exportSchema 选项为 true。否则将导致谬误: Cannot create auto-migrations when export schema is OFF

当主动迁徙须要帮忙时

Room 的主动迁徙无奈检测到数据库上执行的所有可能的变动,因而有时候它们须要一些帮忙。举一个常见的例子,Room 没方法检测到一个数据库表或列是否被重命名或者被删除。在这种状况下,Room 会抛出一个编译谬误,并要求您实现 AutoMigrationSpec。此类容许您指定做出更改的类型,实现一个 AutoMigrationSpec 并应用以下一项或多项来注解:

  • @DeleteTable(tableName)
  • @RenameTable(fromTableName, toTableName)
  • @DeleteColumn(tableName, columnName)
  • @RenameColumn(tableName, fromColumnName, toColumnName)

举个例子,假如咱们将 Doggos 的数据库表重命名为 GoodDoggos。Room 无奈检测到咱们是新建了这个表并删除了 Doggos 表,还是重命名了它以及要保留所有的值。

/* Copyright 2020 Google LLC.  
   SPDX-License-Identifier: Apache-2.0 */

@Database(
   version = 2,
   entities = [GoodDoggos.class],
   autoMigrations = [
        AutoMigration (
            from = 1, 
            to = 2,
            spec = DoggosDatabase.DoggosAutoMigration::class
       )
    ]
)
abstract class DoggosDatabase : RoomDatabase {@RenameTable(fromTableName = "Doggos", toTableName = "GoodDoggos")
    class DoggosAutoMigration: AutoMigrationSpec {}}

迁徙 vs 主动迁徙

何时应用迁徙性能

针对手动迁徙数据库 (manually handle migrations),Room 从 1.0 版本开始就提供了 Migration 类。每当您要更改简单的数据库 Schema 时,您就得应用这个类。举例来说,如果咱们决定将数据库中的一个表拆分成两个不同的表,Room 无奈检测到拆分的执行过程,也不能自动检测到须要挪动的数据。因而这个时候,您须要实现一个 Migration 类,并通过 addMigrations() 的办法将其增加至 databaseBuilder() 中。

/* Copyright 2020 Google LLC.  
   SPDX-License-Identifier: Apache-2.0 */

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

Room.databaseBuilder(applicationContext, DoggosDatabase::class.java, "doggos-database")
    .addMigrations(MIGRATION_1_2,)
    .build()

组合应用「迁徙」与「主动迁徙」

Room 容许将迁徙与主动迁徙联合起来应用。比如说,从版本 1 迁徙到版本 2 能够通过 Migration 来实现,版本 2 迁徙到 3 则能够应用主动迁徙。如果您在同一个版本上同时定义了 Migration 和主动迁徙,那么只有 Migration 会失效。

在底层实现上,主动迁徙会构建一个 Migration 类,因而 这篇文章 具体提到的迁徙逻辑仍然实用。TL;DR: 当数据库被首次拜访时,Room 会查看以后的数据库版本是否与 @Database 中定义的版本不同。如是,Room 会寻找出从此到彼的迁徙门路,届时会间断地执行迁徙操作。

测试主动迁徙

您能够通过 MigrationTestHelper 的测试规定来测试主动迁徙,并与应用 Migration 类雷同的形式调用 helper.runMigrationsAndValidate()。对于测试迁徙的更多信息,欢迎您查看文档: 测试单次迁徙。

总结

主动迁徙性能 (@Database 中的 autoMigration 参数 ) 能够让您轻松的应答数据库 Schema 变动。尽管 Room 能解决许多根本状况,但对于数据库表 / 列的删除或重命名来说,您仍须要实现一个 AutoMigrationSpec。针对其余状况,请持续应用 Migrations 来解决。

该性能现仍处于 alpha 状态,欢迎您通过 issue tracker 踊跃反馈,来帮忙咱们做得更好。

正文完
 0