在不同 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 踊跃反馈,来帮忙咱们做得更好。