Room tidak dapat memverifikasi integritas data


94

Saya mendapatkan error ini saat menjalankan program dengan Room Database

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.

Sepertinya kita perlu mengupdate versi Database, tapi dari mana kita bisa melakukannya di Room?


2
Jika Anda tidak peduli dengan data aplikasi, menghapus semua konten dari pengaturan aplikasi juga dapat membantu, karena itu hanya menghancurkan seluruh DB
O-9

Jawaban:


131

Saat Anda pertama kali menemukan pesan ini, kemungkinan besar Anda akan bekerja dengan versi database yang belum dirilis. Jika demikian, kemungkinan besar Anda sebaiknya tidak menaikkan versi database . Cukup menghapus data aplikasi akan membuat Anda melewati pengecualian.

Jika Anda tidak menaikkan database (disarankan):

Anda harus menghapus data aplikasi aplikasi dari pengaturan Android. Sebagai alternatif, Anda mungkin dapat mencopot pemasangan versi aplikasi sebelumnya dan kemudian memasang versi baru untuk lolos pengecualian. Pendekatan terakhir ini tidak berfungsi dalam kondisi tertentu (seperti ketika izinkan pencadangan diaktifkan)

Karena menghapus data aplikasi selalu berhasil, saya mengambil rute itu setiap saat.

Jika Anda meningkatkan versi database:

Anda perlu menulis kode migrasi database ke akun untuk setiap perubahan pada skema database. Lihat di sini untuk informasi tentang migrasi.

Alternatif untuk menulis kode migrasi database adalah dengan memanggil fallbackToDestructiveMigrationpembuat database Room. Ini mungkin bukan ide yang bagus. Lupa menghapus panggilan ini dan kemudian lupa mengupgrade database akan mengakibatkan kehilangan data.

// Using this fallback is almost certainly a bad idea
Database database = Room.databaseBuilder(context, Database.class, DATABASE_NAME)
        .fallbackToDestructiveMigration()
        .build();

Sekali lagi, tidak perlu menaikkan versi database atau mundur ke migrasi destruktif jika skema database sebelumnya tidak aktif .


4
Saya berharap mereka menyertakan metode fallback lain untuk kasus ini :(
BoD

3
Dalam versi 1.0.0-rc1Room, satu-satunya hal yang berhasil bagi saya adalah meningkatkan versi database.
Dick Lucas

42
Saya memiliki android: allowBackup = "true" di AndroidManifest.xml saya yang mencegah data dihapus bahkan setelah aplikasi di-uninstal. Saya mengatur atribut ini ke false dan kemudian menginstal ulang aplikasi, yang membantu menyingkirkan masalah. Perhatikan bahwa true adalah nilai default untuk allowBackup, jadi jika Anda tidak menggunakannya sama sekali, ini mungkin masih menyebabkan data disimpan.
Bartek

1
@Bartek komentar ini sekarang layak untuk dijawab.
guness

Penjelasan seperti itu! Saya mencopot pemasangan aplikasi lagi dan lagi karena mengapa meningkatkan versi dalam pengembangan? Ya ampun, tidak pernah menyangka bahwa menghapus data dari pengaturan adalah kuncinya. Jawaban bagus. Harus menjadi solusi yang diterima.
sud007

29

Secara default, manifes Android memiliki android:allowBackup="true", Yang memungkinkan aplikasi mempertahankan DB SQLite mereka saat penginstalan ulang.

Misalkan Anda DATABASE_VERSIONawalnya 3 dan kemudian Anda memutuskan untuk mengurangi versi DB dari 3 menjadi 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.
//        }
//    };
}

Anda bisa mencapainya seperti ini

  • Hapus data Aplikasi dari Pengaturan. Ini akan menghapus DB lama (DATABASE_VERSION = 3) dari ponsel
  • Copot Pemasangan Aplikasi Anda
  • Kurangi versi DATABASE_VERSION menjadi 1
  • Bangun dan Instal Ulang Aplikasi Anda

Ini adalah praktik yang baik untuk tetap DATABASE_VERSIONkonstan.


1
Apakah itu tidak akan memengaruhi pengguna yang akan memperbarui aplikasi dari play store?
nimi0112

1
Saya telah mengikuti dengan cara yang sama, tetapi tidak berhasil. Bahkan saya mencoba menginstal pada perangkat baru dari Android Studio, itu menunjukkan kesalahan yang sama: x
Sadat

@ nimi0112 Untuk varian rilis Anda, Anda harus mengizinkan cadangan, namun untuk varian debug Anda, Anda dapat mematikannya
Chad Mx

25

android: allowBackup = "true" di dalam AndroidManifest.xml mencegah data dihapus bahkan setelah aplikasi di-uninstal.

Tambahkan ini ke manifes Anda:

android:allowBackup="false"

dan instal ulang aplikasi.

Catatan: Pastikan Anda mengubahnya kembali ke true nanti jika Anda ingin backup otomatis.

Solusi lain:

Periksa identitasHash file json lama Anda dan file json baru di folder apps \ schema.

Jika identitasHash berbeda, itu akan memberikan kesalahan itu. Cari tahu apa yang telah Anda ubah dengan membandingkan kedua file json jika Anda tidak ingin mengubah apa pun.

Pastikan Anda memiliki exportSchema = true.

@Database(entities = {MyEntity.class, ...}, version = 2, exportSchema = true)

file skema json:

  "formatVersion": 1,
  "database": {
    "version": 2,
    "identityHash": "53cc5ef34d2ebd33c8518d79d27ed012",
    "entities": [
      {

kode:

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.");
    }
}

20

Jawaban Aniruddh Parihar memberi saya petunjuk dan itu terpecahkan.

Cari kelas yang sudah Anda kembangkan RoomDatabase. Di sana Anda akan menemukan versi seperti di bawah ini:

@Database(entities = {YourEntity.class}, version = 1)

tingkatkan saja versi dan masalah terpecahkan.


11

Sangat sederhana seperti yang ditunjukkan pada log

Looks like you've changed schema but forgot to update the Database version number. 
You can simply fix this by increasing the version number.

Cukup buka kelas Versi Database Anda dan tingkatkan versi DB Anda dengan meningkatkan 1 dari saat ini.

Sebagai Contoh: Temukan anotasi @Database dalam proyek Anda seperti di bawah ini

@Database(entities = {YourEntityName.class}, version = 1)

Di sini versi = 1, adalah versi database, Anda harus menambahnya satu per satu, Itu saja.


1
Ya saya mendapat kesalahan itu, itulah mengapa saya sebutkan juga itu It seems we need to update database version. Tetapi saya tidak mengerti di mana versi itu disebutkan. Terima kasih untuk petunjuk itu.
Ravi

Anda telah mengubah pesan kesalahan tetapi belum memberikan informasi tambahan untuk mengatasi kebingungan pembuat poster asli.
Carl Rossman

@CarlRossman: Anda harus menemukan kelas Database Anda di proyek Anda di mana Anda telah menggunakan anotasi Database, di kelas itu Anda akan menemukan versi Database (nilai Integer), cukup tingkatkan satu per satu dari saat ini.
Aniruddh Parihar

7

1: - Sepertinya kita perlu memperbarui versi database (selisih 1)

masukkan deskripsi gambar di sini

2. Copot pemasangan aplikasi atau Hapus data aplikasi


6

Di ponsel android:

Copot pemasangan aplikasi atau Hapus data aplikasi

Untuk menghapus data aplikasi: Buka pengaturan -> Aplikasi -> Pilih aplikasi Anda -> Penyimpanan -> Hapus data

Penghapusan (dan instal ulang) tidak berfungsi di setiap kasus, jadi coba hapus data terlebih dahulu!


Ya itu berhasil. Tapi anehnya saya mendapatkan masalah ini di perangkat yang terhapus sepenuhnya dan baru saja disiapkan. Tapi hanya membersihkan data diselesaikan.
Ajith Memana

Ini tidak boleh dilakukan pada produksi. Anda tidak boleh memaksa semua pengguna Anda untuk menghapus data dari aplikasi. Lebih baik menulis kode migrasi dengan meningkatkan versinya 1 di database Room Anda.
Rajeev Jayaswal

5

Dalam kasus saya android:allowBackup="false"membuatnya dari true menjadi false berfungsi, karena ini telah memberi saya mimpi buruk sebelumnya juga, ini adalah hal paling aneh mengapa pengaturan ini diaktifkan secara default!


5

Untuk memperbaiki masalah di kotlin:

Pertama

@Database(entities = [Contact::class], version = 2)

Kedua

val MIGRATION_1_2 = object : Migration(1, 2) {
        override fun migrate(database: SupportSQLiteDatabase) {
            database.execSQL("ALTER TABLE Contact ADD COLUMN seller_id TEXT NOT NULL DEFAULT ''")
        }
    }

Ketiga

private fun buildDatabase(context: Context) = Room.databaseBuilder(
            context.applicationContext,
            EpayDatabase::class.java,
            "epay"
        )
            .addMigrations(MIGRATION_1_2)
            .build()

Untuk lebih jelasnya, lihat dokumentasi resmi


4

Masalah ini sebagian besar terjadi dalam pengembangan.

Jika Anda mengubah skema, yaitu, ganti nama / tambahkan / modifikasi kelas Anda yang berisi entitas tabel, integritas antara keluar dari db di build sebelumnya bertentangan dengan build baru.

hapus data aplikasi atau instal build baru setelah meng-uninstal build sebelumnya .

Sekarang, db lama tidak akan konflik dengan yang lebih baru.


Setelah itu masih macet
user7856586

apa pengecualiannya? tolong pasang log untuk mempersempit masalah.
Extremis II

2
Terima kasih, semuanya baik-baik saja sekarang. Saya membaca android:allowBackup="true"dan menggunakannya dengan bijak
user7856586

1
@ user7856586 Jadi bagaimana dengan allowBackup? Bisakah Anda mencerahkan kami dengan kebijaksanaan Anda?
konyol

@Ridcully Anda dapat membaca tentang itu di sini Mengapa Anda sangat marah?
pengguna7856586

3

Dalam kasus saya, saya memiliki kelas AppDatabase.

@Database(entities = {GenreData.class, MoodData.class, SongInfo.class,
    AlbumsInfo.class, UserFolderListsData.class, UserPlaylistResponse.PlayLists.class, InternetConnectionModel.class}, version = 3, exportSchema = false)

Saya memperbarui nomor versi ini dan itu menyelesaikan masalah. Masalah muncul karena saya telah menambahkan properti di kelas SongInfo dan lupa memperbarui nomor versi.

Semoga bisa membantu seseorang.


2

Jika Anda mengupgrade versi Room ke 1.0.0-alpha9 dari versi lama, silakan kunjungi artikel di bawah ini. Artikel Sangat Bagus untuk Bermigrasi dari versi lama ke versi 1.0.0-alpha9.

https://medium.com/@manuelvicnt/android-room-upgrading-alpha-versions-needs-a-migration-with-kotlin-or-nonnull-7a2d140f05b9

Dalam Room Versi Baru 1.0.0-alpha9 Room menambahkan dukungan untuk batasan NOT NULL.

Itu akan mengubah skema yang dihasilkan Room. Karena mengubah skema, ini juga mengubah identityHash dari DB dan yang digunakan oleh Room untuk mengidentifikasi setiap versi DB secara unik. Oleh karena itu, diperlukan migrasi


2

Dalam kasus saya, ContentProvider dan database ruangan bekerja sama, jadi pertama-tama hapus semua callback ContentProvider di seluruh aplikasi dengan kelas database yang memperluas SqlLiteOpenHelper Class


2

Dalam kasus saya, saya menggunakan transaksi di dalam migrasi dan Room tidak dapat memperbarui hash menggunakan Pembantu Migrasi

@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() 
}

Saya berjuang selama beberapa jam dan inilah solusinya !! Terima kasih!!
Javier

1
Dalam contoh di atas, bukan transaksi yang menjadi masalah. Anda lupa menyetel transaksi berhasil sebelum mengakhirinya: <pre> <code> database.beginTransaction () database.setTransactionSuccessful () database.endTransaction () </code> </pre>
birukoff

2
@Database(entities = {Tablename1.class, Tablename2.class}, version = 3, exportSchema = false)

Ubah nomor versi di kelas RoomDatabase Anda. Tingkatkan nomor versi.


2

Jika peningkatan versi skema tidak berhasil, berikan migrasi database Anda. Untuk melakukannya, Anda perlu mendeklarasikan migrasi di pembuat database:

Room.databaseBuilder(context, RepoDatabase.class, DB_NAME)
  .addMigrations(FROM_1_TO_2)
.build();

static final Migration FROM_1_TO_2 = new Migration(1, 2) {
@Override
public void migrate(final SupportSQLiteDatabase database) {
    database.execSQL("ALTER TABLE Repo 
                     ADD COLUMN createdAt TEXT");
    }
};

Ya, ini Jalan yang tepat
Bipin Bharti

1

Saya baru saja mengalami masalah serupa dalam pengujian espresso dan satu-satunya hal yang memperbaikinya adalah menghapus data dan juga mencopot aplikasi uji androidx seperti:

adb uninstall androidx.test.orchestrator
adb uninstall androidx.test.services

0

Dalam kasus saya, saya membuat pembaruan ke database yang akan saya paketkan sebelumnya dengan aplikasi saya. Tidak ada saran di sini yang berhasil. Tetapi akhirnya saya menemukan bahwa saya dapat membuka file .db dalam program database (saya menggunakan "DB Browser for SQLite"), dan secara manual mengubah "Versi pengguna" dari 2 kembali ke 1. Setelah itu, ini bekerja dengan sempurna.

Saya kira setiap pembaruan yang Anda buat mengubah versi pengguna ini, dan inilah mengapa saya terus mendapatkan kesalahan ini.


Bisakah Anda membantu saya dengan hal yang sama? Saya tidak dapat menemukan versi di DB Browser untuk SQLite
GreenROBO

Letaknya di bawah tab "Edit pragmas". Ini disebut "Versi Pengguna".
Gavin Wright

Iya. Saya mendapatkannya. Terima kasih atas bantuannya Gavin :)
GreenROBO

-1

Dalam kasus saya, saya mencoba semua hal di atas. Sepertinya tidak ada yang berhasil, jadi solusi bagi saya hanyalah mengatur android:allowBackup="false", menginstal aplikasi, lalu mengaturnya kembali ke true

Semoga bisa membantu orang lain :)


1
Persis seperti inilah yang telah saya jawab, mengapa mengulangi jawabannya?
Divyanshu Negi

-2

Saya mendapat kesalahan yang sama selama program pelatihan Codelabs. Dimana Dalam satu sesi pelatihan saya membuat sebuah proyek dan itu berjalan dengan sukses dengan semua operasi database. Pada sesi berikutnya, saya bekerja dengan repo yang berbeda, tetapi itu merupakan perpanjangan dari proyek sebelumnya, Dari versi pertama aplikasi yang diperpanjang, hanya saya yang mendapat kesalahan.

Mungkin Studio menyimpan teknik autentikasi dengan database ruangan yang hilang dengan build baru.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.