ルームデータベースでプログラムを実行しているときにこのエラーが発生します
Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number.
You can simply fix this by increasing the version number.
データベースのバージョンを更新する必要があるようですが、どこからRoomでそれを行うことができますか?
このメッセージに最初に出くわしたときは、データベースの未リリースバージョンに対して作業している可能性が高いでしょう。その場合、ほとんどの場合、データベースのバージョンをインクリメントしないでください。アプリのデータを消去するだけで、例外に合格します。
データベースを増分しない場合(推奨):
Android設定からアプリケーションのアプリデータを消去する必要があります。または、以前のアプリバージョンをアンインストールしてから、新しいバージョンをインストールして例外を渡すこともできます。この後者のアプローチは、特定の条件下では機能しません(バックアップを許可する場合など)
アプリケーションデータのクリアは常に機能するため、毎回そのルートを取ります。
データベースのバージョンを増やす場合:
データベーススキーマへの変更を考慮して、データベース移行コードを記述する必要があります。移行については here をご覧ください。
データベース移行コードを記述する代わりに、RoomデータベースビルダーでfallbackToDestructiveMigration
を呼び出すこともできます。これはおそらく良い考えではありません。この呼び出しを削除し忘れて、データベースのアップグレードを忘れると、データが失われます。
// Using this fallback is almost certainly a bad idea
Database database = Room.databaseBuilder(context, Database.class, DATABASE_NAME)
.fallbackToDestructiveMigration()
.build();
繰り返しますが、以前のデータベーススキーマがライブに存在しない場合、データベースバージョンをインクリメントしたり、破壊的な移行にフォールバックする必要はありません。
デフォルトでは、AndroidマニフェストにはAndroid:allowBackup="true"
があり、これによりアプリは再インストール時にSQLite DBを保持できます。
DATABASE_VERSION
が最初は3だった場合、DBバージョンを3から1に減らすことにします。
@Database(entities = {CallRecording.class}, version = DATABASE_VERSION)
public abstract class AppDatabase extends RoomDatabase {
public abstract RecordingDAO recordingDAO();
// static final Migration MIGRATION_1_2 = new Migration(1, 2) {
// @Override
// public void migrate(SupportSQLiteDatabase database) {
// // Since we didn't alter the table, there's nothing else to do here.
// }
// };
}
このように達成できます
DATABASE_VERSION
を一定に保つことをお勧めします。
ログに示されているように、その非常にシンプルな
Looks like you've changed schema but forgot to update the version number.
You can simply fix this by increasing the version number.
データベースクラスに移動し、現在のバージョンから1を増やしてDBバージョンをアップグレードします。
Aniruddh Parihar の答えは私にヒントを与え、解決しました。
RoomDatabase
を拡張したクラスを検索します。そこには以下のようなバージョンがあります:
@Database(entities = {YourEntity.class}, version = 1)
バージョンを上げるだけで問題は解決します。
AndroidManifest.xml内のAndroid:allowBackup = "true"は、アプリがアンインストールされた後でもデータが消去されないようにします。
これをマニフェストに追加します。
Android:allowBackup="false"
アプリを再インストールします。
注:自動バックアップが必要な場合は、後でそれをtrueに戻してください。
別のソリューション:
Apps\schemaフォルダーにある古いjsonファイルと新しいjsonファイルのidentityHashを確認します。
IdentityHashが異なる場合、そのエラーが発生します。何も変更したくない場合は、両方のjsonファイルを比較して、変更内容を確認します。
ExportSchema = trueであることを確認してください。
@Database(entities = {MyEntity.class, ...}, version = 2, exportSchema = true)
jsonスキーマファイル:
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "53cc5ef34d2ebd33c8518d79d27ed012",
"entities": [
{
コード:
private void checkIdentity(SupportSQLiteDatabase db) {
String identityHash = null;
if (hasRoomMasterTable(db)) {
Cursor cursor = db.query(new SimpleSQLiteQuery(RoomMasterTable.READ_QUERY));
//noinspection TryFinallyCanBeTryWithResources
try {
if (cursor.moveToFirst()) {
identityHash = cursor.getString(0);
}
} finally {
cursor.close();
}
}
if (!mIdentityHash.equals(identityHash) && !mLegacyHash.equals(identityHash)) {
throw new IllegalStateException("Room cannot verify the data integrity. Looks like"
+ " you've changed schema but forgot to update the version number. You can"
+ " simply fix this by increasing the version number.");
}
}
この問題は主に開発時に発生します。
スキーマを変更する場合、つまり、テーブルエンティティを含むクラスの名前を変更/追加/変更すると、以前のビルドで終了したdb間の整合性が新しいビルドと競合します。
アプリのデータを消去するまたは前のビルドをアンインストールした後に新しいビルドをインストールする。
現在、古いデータベースは新しいデータベースと競合しません。
私の場合、Android:allowBackup="false"
がtrueからfalseに機能するようになりました。これは以前にも悪夢をもたらしたので、これがこの設定がデフォルトで有効になっている最も奇妙なことです!
私の場合、AppDatabaseクラスがありました。
@Database(entities = {GenreData.class, MoodData.class, SongInfo.class,
AlbumsInfo.class, UserFolderListsData.class, UserPlaylistResponse.PlayLists.class, InternetConnectionModel.class}, version = 3, exportSchema = false)
このバージョン番号を更新し、問題を解決しました。 SongInfoクラスにプロパティを追加し、バージョン番号を更新するのを忘れていたため、問題が発生しました。
それが誰かを助けることを願っています。
Android電話:
アプリのアンインストールまたはアプリデータのクリア
アプリのデータを削除するには:設定->アプリ->アプリを選択->ストレージ->データを消去
アンインストール(および再インストール)はすべての場合に機能するわけではないため、データをクリアしてみてください!
ルームバージョンを古いバージョンから1.0.0-alpha9にアップグレードする場合は、以下の記事をご覧ください。古いバージョンから1.0.0-alpha9バージョンへの移行に関する非常に良い記事。
ルームの新しいバージョン1.0.0-alpha9ルームでは、NOT NULL制約のサポートが追加されています。
これにより、Roomが生成するスキーマが変更されます。スキーマを変更するため、DBのidentityHashも変更され、RoomがすべてのDBバージョンを一意に識別するために使用されます。したがって、移行が必要です
私の場合、移行内でトランザクションを使用していましたが、ルームは移行ヘルパーを使用してハッシュを更新できませんでした
@get:Rule
val migrationTestHelper: MigrationTestHelper =
MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
C2GDatabase::class.Java.canonicalName,
FrameworkSQLiteOpenHelperFactory())
/* Testing method throws error*/
db = migrationTestHelper.runMigrationsAndValidate(C2GDatabase.DB_NAME,
3,
false,
C2GDatabase.Migration_1_2(),
C2GDatabase.Migration_2_3())
override fun migrate(database: SupportSQLiteDatabase) {
/**
Error
database.beginTransaction()
**/
database.execSQL("PRAGMA foreign_keys=off;")
database.execSQL("ALTER TABLE user RENAME TO user_old;")
database.execSQL("CREATE TABLE user ( id_user INTEGER PRIMARY KEY AUTOINCREMENT, external_id INTEGER NOT NULL;")
database.execSQL("INSERT INTO user ( id_user, external_id ) " +
" SELECT id_user, external_id" +
" FROM user_old;")
database.execSQL("CREATE UNIQUE INDEX idx_unique_user ON user (external_id);")
database.execSQL("PRAGMA foreign_keys=on;")
database.execSQL("DROP TABLE user_old;")
//database.endTransaction()
}
私の場合、ContentProviderとルームデータベースは連携して動作するため、最初にSqlLiteOpenHelperクラスを拡張するデータベースクラスを使用して、アプリケーション全体のContentProviderのすべてのコールバックを削除します
エスプレッソテストでも同様の問題が発生しましたが、それを修正したのは、データをクリアし、次のようなandroidxテストapkをアンインストールすることだけでした:
adb uninstall androidx.test.orchestrator
adb uninstall androidx.test.services
私の場合、上記のすべてを試しました。何も機能していないように思えたので、私にとっての解決策は、単にAndroid:allowBackup="false"
を設定し、アプリをインストールしてからtrueに戻すことでした。
それが他の人を助けることを願っています:)