Android Architecture Component Room永続化データベース(5)Roomデータベースの移行
6225 ワード
本文はブロガーのオリジナルの文章で、みんなが転載することを歓迎します!
ただし転載は出典を明記してください.https://blog.csdn.net/t000818/article/details/84303795,本文出典:【唐宏宇のブログ】
アプリケーションで機能を追加および変更する場合は、データベース・エンティティ・クラスを変更して変更をマッピングする必要があります.ユーザーが最新バージョンのアプリケーションに更新した場合、特にリモート・サーバからデータをリカバリできない場合は、既存のすべてのデータを失うことを望んでいません.
Room persistence libraryライブラリは、Migrationクラスを作成してユーザーデータを保持できます.各MigrationクラスはstartVersionとendVersionを指定します.実行時、Roomは各Migrationクラスのmigrate()メソッドを実行し、正しい順序でデータベースをより高いバージョンに移行します.
Kotlin表記:
Java書き方:
警告:移行ロジックを予想通りに実行するには、クエリーの定数を参照するのではなく、完全なクエリーを使用します.
移行プロセスが完了すると、Roomはモデルを検証し、移行が正しく行われていることを確認します.Roomが問題を発見すると、不一致情報を含む例外が放出されます.
データ移行のテスト
移行は容易ではありませんが、正しく作成されていないとアプリケーションがクラッシュする可能性があります.アプリケーションの安定性を維持するには、事前に移行をテストする必要があります.Roomは、このテストプロセスを支援するためのテストMaven依存ライブラリを提供します.ただし、この依存ライブラリを有効にするには、データベースのモデルをエクスポートする必要があります.
モデルのエクスポート
コンパイル時、Roomはデータベースのモデル情報をJSONファイルにエクスポートします.スキーマをエクスポートするにはbuild.gradleファイルでroomを設定します.schemaLocationデプロセッサのプロパティは、次のコード・セグメントに示されています.
build.gradle
テストパッケージにはMigrationTestHelperクラスがあり、これらのモデルファイルを読み込むことができます.JUnit 4 TestRuleインタフェースも実装されているため、作成したデータベースを管理できます.
次のコード・セグメントには、移行テストの例が表示されます.
Kotlin表記:
Java書き方:
失われた移行経路を優雅に処理
データベースのモデルを更新しても、一部のデバイスのデータベースでは古いモードバージョンが使用される場合があります.Roomがデバイスのデータベースを古いバージョンから現在のバージョンにアップグレードする移行ルールが見つからない場合、IllegalStateExceptionが発生します.
このような状況でアプリケーションがクラッシュしないようにするには、データベースの作成時にfallbackToDestructiveMigration()ビルダーメソッドを呼び出します.
Kotlin表記:
Java書き方:
アプリケーションのデータベース構築ロジックにこの句を追加することで、Roomがデータベース・モデルのバージョン間の移行パスが欠けている場合に、アプリケーションのデータベース・テーブルを破壊的に再作成することを通知できます.
警告:このオプションをアプリケーションのデータベース・ビルダーで構成すると、Roomは移行パスが見つからないときにデータベース・テーブルのすべてのデータを永続的に削除します.破壊的なロールバックロジックには、いくつかの追加オプションがあります.移行パスを使用して解決できないアーキテクチャ履歴の特定のバージョンでエラーが発生した場合は、 試行モード降格時のみ破壊再作成を実行するには、 に変更します.
ただし転載は出典を明記してください.https://blog.csdn.net/t000818/article/details/84303795,本文出典:【唐宏宇のブログ】
アプリケーションで機能を追加および変更する場合は、データベース・エンティティ・クラスを変更して変更をマッピングする必要があります.ユーザーが最新バージョンのアプリケーションに更新した場合、特にリモート・サーバからデータをリカバリできない場合は、既存のすべてのデータを失うことを望んでいません.
Room persistence libraryライブラリは、Migrationクラスを作成してユーザーデータを保持できます.各MigrationクラスはstartVersionとendVersionを指定します.実行時、Roomは各Migrationクラスのmigrate()メソッドを実行し、正しい順序でデータベースをより高いバージョンに移行します.
Kotlin表記:
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, `name` TEXT, " +
"PRIMARY KEY(`id`))")
}
}
val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Book ADD COLUMN pub_year INTEGER")
}
}
Room.databaseBuilder(applicationContext, MyDb::class.java, "database-name")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3).build()
Java書き方:
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.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();
警告:移行ロジックを予想通りに実行するには、クエリーの定数を参照するのではなく、完全なクエリーを使用します.
移行プロセスが完了すると、Roomはモデルを検証し、移行が正しく行われていることを確認します.Roomが問題を発見すると、不一致情報を含む例外が放出されます.
データ移行のテスト
移行は容易ではありませんが、正しく作成されていないとアプリケーションがクラッシュする可能性があります.アプリケーションの安定性を維持するには、事前に移行をテストする必要があります.Roomは、このテストプロセスを支援するためのテストMaven依存ライブラリを提供します.ただし、この依存ライブラリを有効にするには、データベースのモデルをエクスポートする必要があります.
モデルのエクスポート
コンパイル時、Roomはデータベースのモデル情報をJSONファイルにエクスポートします.スキーマをエクスポートするにはbuild.gradleファイルでroomを設定します.schemaLocationデプロセッサのプロパティは、次のコード・セグメントに示されています.
build.gradle
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":
"$projectDir/schemas".toString()]
}
}
}
}
テストパッケージにはMigrationTestHelperクラスがあり、これらのモデルファイルを読み込むことができます.JUnit 4 TestRuleインタフェースも実装されているため、作成したデータベースを管理できます.
次のコード・セグメントには、移行テストの例が表示されます.
Kotlin表記:
@RunWith(AndroidJUnit4::class)
class MigrationTest {
private val TEST_DB = "migration-test"
@Rule
val helper: MigrationTestHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
MigrationDb::class.java.canonicalName,
FrameworkSQLiteOpenHelperFactory()
)
@Test
@Throws(IOException::class)
fun migrate1To2() {
var db = helper.createDatabase(TEST_DB, 1).apply {
// db has schema version 1. insert some data using SQL queries.
// You cannot use DAO classes because they expect the latest schema.
execSQL(...)
// Prepare for the next version.
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.
}
}
Java書き方:
@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.
}
}
失われた移行経路を優雅に処理
データベースのモデルを更新しても、一部のデバイスのデータベースでは古いモードバージョンが使用される場合があります.Roomがデバイスのデータベースを古いバージョンから現在のバージョンにアップグレードする移行ルールが見つからない場合、IllegalStateExceptionが発生します.
このような状況でアプリケーションがクラッシュしないようにするには、データベースの作成時にfallbackToDestructiveMigration()ビルダーメソッドを呼び出します.
Kotlin表記:
Room.databaseBuilder(applicationContext, MyDb::class.java, "database-name")
.fallbackToDestructiveMigration()
.build()
Java書き方:
Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
.fallbackToDestructiveMigration()
.build();
アプリケーションのデータベース構築ロジックにこの句を追加することで、Roomがデータベース・モデルのバージョン間の移行パスが欠けている場合に、アプリケーションのデータベース・テーブルを破壊的に再作成することを通知できます.
警告:このオプションをアプリケーションのデータベース・ビルダーで構成すると、Roomは移行パスが見つからないときにデータベース・テーブルのすべてのデータを永続的に削除します.破壊的なロールバックロジックには、いくつかの追加オプションがあります.
fallbackToDestructiveMigrationFrom()
を使用します.この方法は、データベースが問題のあるバージョンから移行しようとした場合にのみ、Roomにロールバックロジックを使用することを意味します.fallbackToDestructiveMigrationOnDowngrade()