源文档链接
数据迁移
如果app添加/修改feature时,需要重定义实体类来反映这些变化。当用户更新后,要保留原有数据,特别是不能从服务端复原的数据
Room允许编写Migration
类来进行数据迁移。每个Migration
类会标明startVersion
和endVersioh
。在运行时,Room会运行每个Migration
类中的migrate()方法,使用正确的顺序进行数据迁移
注意:如果没有提供必要的
migrations
,Room会重建数据库,意味着会失去之前的数据
Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
+ "`name` TEXT, PRIMARY KEY(`id`))");
}
};
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE Book "
+ " ADD COLUMN pub_year INTEGER");
}
};
注意:为了保持迁移逻辑按预期运行,请使用完整查询,而不是引用表示查询的常量。
在数据迁移完成后,Room会验证迁移是否正确,如果存在问题,会抛出异常信息
迁移测试
为了保证应用的稳定性,需要对数据迁移进行测试,Room提供了测试仓库。但是,需要将数据库导出才能工作
仓库:android.arch.persistence.room:testing
导出
Room会将数据库的信息导出到JSON文件中,需要在build.gradle
中设置room.schemaLocation
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":
"$projectDir/schemas".toString()]
}
}
}
}
应该保存所有的导出JSON文件,以便Room创建老的版本用于测试
添加测试库依赖后,指定JSON文件位置
android {
...
sourceSets {
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
}
}
使用MigrationTestHelper
解析JSON文件,
测试用例:
@RunWith(AndroidJUnit4.class)
public class MigrationTest {
private static final String TEST_DB = "migration-test";
@Rule
public MigrationTestHelper helper;
public MigrationTest() {
helper = new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
MigrationDb.class.getCanonicalName(),
new FrameworkSQLiteOpenHelperFactory());
}
@Test
public void migrate1To2() throws IOException {
SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 1);
// db has schema version 1. insert some data using SQL queries.
// You cannot use DAO classes because they expect the latest schema.
db.execSQL(...);
// Prepare for the next version.
db.close();
// Re-open the database with version 2 and provide
// MIGRATION_1_2 as the migration process.
db = helper.runMigrationsAndValidate(TEST_DB, 2, true, MIGRATION_1_2);
// MigrationTestHelper automatically verifies the schema changes,
// but you need to validate that the data was migrated properly.
}
}