Oda veri bütünlüğünü doğrulayamıyor


92

Oda Veritabanı ile programı çalıştırırken bu hatayı alıyorum

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.

Görünüşe göre Veritabanı sürümünü güncellememiz gerekiyor, ancak bunu Oda'da nereden yapabiliriz?


2
Uygulamanın verilerini umursamıyorsanız, tüm içeriği uygulama ayarlarından silmek de yardımcı olabilir, çünkü bu yalnızca tüm DB'yi yok eder
O-9

Yanıtlar:


131

Bu mesajla ilk karşılaştığınızda, büyük olasılıkla veritabanının yayınlanmamış bir sürümüne karşı çalışacaksınız. Durum buysa, büyük olasılıkla veritabanı sürümünü artırmamalısınız . Basitçe uygulama verilerini temizlemek, istisnayı geçmenizi sağlar.

Veritabanını artırmazsanız (önerilir):

Uygulamanın uygulama verilerini Android ayarlarından temizlemelisiniz. İstisnayı geçmek için alternatif olarak önceki uygulama sürümünü kaldırabilir ve ardından yeni sürümü yükleyebilirsiniz. Bu ikinci yaklaşım, belirli koşullar altında çalışmaz (yedeklemeye izin verme etkinleştirildiğinde olduğu gibi)

Uygulama verilerini temizlemek her zaman işe yaradığından, her seferinde bu rotayı kullanıyorum.

Veritabanı sürümünü artırırsanız:

Veritabanı şemasındaki herhangi bir değişikliği hesaba katmak için veritabanı geçiş kodu yazmanız gerekecektir. Taşıma hakkında bilgi için buraya bakın .

Veritabanı geçiş kodu yazmanın alternatifi fallbackToDestructiveMigration, Oda veritabanı oluşturucusunu çağırmaktır . Bu muhtemelen iyi bir fikir değil. Bu aramayı kaldırmayı ve ardından veritabanını yükseltmeyi unutmak veri kaybına neden olur.

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

Yine, önceki veritabanı şeması vahşi ortamda yaşamıyorsa ne veritabanı sürümünü artırmak ne de yıkıcı geçişe geri dönmek gerekli değildir .


4
Keşke bu vaka için başka bir geri dönüş yöntemi dahil etseler :(
BoD

3
1.0.0-rc1Room sürümünde benim için çalışan tek şey veritabanı sürümünü yükseltmekti.
Dick Lucas

42
AndroidManifest.xml dosyamda, uygulama kaldırıldıktan sonra bile verilerin temizlenmesini engelleyen android: allowBackup = "true" vardı. Bu özelliği yanlış olarak ayarladım ve ardından uygulamayı yeniden yükledim, bu da sorundan kurtulmaya yardımcı oldu. AllowBackup için varsayılan değerin true olduğunu unutmayın; bu nedenle, onu hiç kullanmazsanız, yine de verilerin tutulmasına neden olabilir.
Bartek

1
@Bartek bu yorum artık bir cevap olmayı hak ediyor.
silahsız

Böyle bir açıklama! Uygulamayı tekrar tekrar kaldırıyordum çünkü neden geliştirme aşamasındaki sürümü yükseltin? Tanrım, verileri ayarlardan temizlemenin ileriye dönük anahtar olduğunu hiç düşünmemiştim. Güzel cevap. Kabul edilen çözüm olmalı.
sud007

29

Varsayılan olarak Android manifestinde android:allowBackup="true", Uygulamaların yeniden yükleme sırasında SQLite DB'lerini sürdürmesine izin veren.

Diyelim ki DATABASE_VERSIONbaşlangıçta 3'ünüz ve sonra DB sürümünü 3'ten 1'e düşürmeye karar veriyorsunuz.

@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.
//        }
//    };
}

Bunu böyle başarabilirsin

  • Ayarlardan Uygulama verilerini temizleyin. Bu, eski DB'yi (DATABASE_VERSION = 3) telefondan kaldıracak
  • Uygulamanızı kaldırın
  • DATABASE_VERSION sürümünü 1'e düşür
  • Uygulamanızı Oluşturun ve Yeniden Yükleyin

DATABASE_VERSIONSabit tutulması iyi bir uygulamadır .


1
Uygulamayı Play Store'dan güncelleyecek kullanıcıları etkilemeyecek mi?
nimi0112

1
Ben de aynı yolu izledim ama işe yaramadı. Android Studio'dan yeni bir cihaza yüklemeye çalışıyorum bile, aynı hatayı gösteriyor: x
Sadat

@ nimi0112 Yayın varyantınız için yedeklemeye izin vermelisiniz, ancak hata ayıklama varyantınız için bunu kapatabilirsiniz
Chad Mx

25

AndroidManifest.xml içindeki android: allowBackup = "true", uygulama kaldırıldıktan sonra bile verilerin temizlenmesini engeller.

Bunu bildiriminize ekleyin:

android:allowBackup="false"

ve uygulamayı yeniden yükleyin.

Not: Otomatik yedeklemeler istiyorsanız, daha sonra tekrar doğru olarak değiştirdiğinizden emin olun.

Başka bir çözüm:

Eski json dosyanızın identHash'ını ve apps \ schema klasöründeki yeni json dosyasını kontrol edin.

IdentHash farklı ise bu hatayı verecektir. Hiçbir şeyi değiştirmek istemiyorsanız, her iki json dosyasını karşılaştırarak neleri değiştirdiğinizi öğrenin.

ExportSchema = true olduğundan emin olun.

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

json şema dosyası:

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

kod:

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

19

Aniruddh Parihar'ın cevabı bana bir ipucu verdi ve çözüldü.

Uzattığınız bir sınıfı arayın RoomDatabase. Orada aşağıdaki gibi bir versiyon bulacaksınız:

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

sadece sürümü artırın ve sorun çözüldü.


12

Günlükte gösterildiği gibi çok basit

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

Basitçe Veritabanı Sürümü sınıfınıza gidin ve mevcut olanı 1 artırarak DB sürümünüzü yükseltin.


1
Evet bu hatayı aldım, bu yüzden söz konusu olandan da bahsetmiştim It seems we need to update database version. Ama o versiyondan bahsedildiği yere ulaşamadım. Her neyse, bu ipucu için teşekkürler.
Ravi

7

1: - Veritabanı sürümünü güncellememiz gerekiyor gibi görünüyor (1 artırın)

görüntü açıklamasını buraya girin

2. Uygulamayı kaldırın veya Uygulama verilerini temizleyin


6

Android telefonda:

Uygulamayı kaldırın veya Uygulama verilerini temizleyin

Uygulama verilerini silmek için: Ayarlar -> Uygulamalar -> Uygulamanızı seçin -> Depolama -> Verileri temizle

Kaldırma (ve yeniden yükleme) her durumda çalışmaz, bu nedenle önce verileri temizlemeyi deneyin!


Evet işe yaradı. Ama garip bir şekilde bu sorunu tamamen silinen ve şimdi yeni kurulan bir cihazda alıyordum. Ancak çözülen verileri temizlemek.
Ajith Memana

Bu, üretimde yapılmamalıdır. Tüm kullanıcılarınızı uygulamadaki verileri temizlemeye zorlamamalısınız. Oda veritabanınızda sürümü 1 artırarak geçiş kodu yazmak daha iyidir.
Rajeev Jayaswal

5

Benim durumumda android:allowBackup="false", bunu doğrudan yanlışa çevirmek işe yaradı, çünkü bu bana daha önce de kabuslar verdi, bu en tuhaf şey, bu ayarın varsayılan olarak etkin olmasının nedeni bu!


5

Kotlin'deki sorunu çözmek için:

İlk

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

İkinci

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 ''")
        }
    }

Üçüncü

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

Daha fazla ayrıntı için resmi belgelere bakın


4

Bu sorun çoğunlukla geliştirme aşamasında ortaya çıkar.

Şemanızı değiştirirseniz, yani tablo varlığını içeren sınıfınızı yeniden adlandırın / ekleyin / değiştirin, önceki derlemenizdeki db'den çıkma arasındaki bütünlük yeni derlemeyle çakışır.

önceki yapıyı kaldırdıktan sonra uygulama verilerini temizleyin veya yeni derlemeyi yükleyin .

Şimdi, eski db yenisiyle çelişmeyecek.


Bundan sonra hala çöküyor
user7856586

istisna nedir? sorunu daraltmak için lütfen günlüğü koyun.
Extremis II

2
Teşekkürler, şimdi her şey yolunda. Bunu android:allowBackup="true"akıllıca okudum ve kullanıyorum
user7856586

1
@ user7856586 Peki ya allowBackup? Bizi bilgeliğinizle aydınlatır mısınız?
ridcully at

@Ridcully bu konuda okuyabilirsiniz burada çok kızgın Neden?
user7856586

3

Benim durumumda bir AppDatabase sınıfım vardı.

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

Bu sürüm numarasını güncelledim ve sorunu çözdüm. SongInfo sınıfına bir özellik eklediğim ve sürüm numarasını güncellemeyi unuttuğum için sorun ortaya çıktı.

Umarım birine yardımcı olur.


2

Oda sürümünü eski sürümden 1.0.0-alpha9'a yükseltiyorsanız, lütfen aşağıdaki makaleyi ziyaret edin. Eski sürümden 1.0.0-alpha9 sürümüne Geçiş için Çok İyi Bir Makale.

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

Odada Yeni Sürüm 1.0.0-alpha9 Room NOT NULL kısıtlaması için destek ekler.

Bu, Room'un oluşturduğu şemayı değiştirecek. Şemayı değiştirdiği için, DB'nin IdentityHash değerini de değiştirir ve Room tarafından her DB sürümünü benzersiz bir şekilde tanımlamak için kullanılır. Bu nedenle bir göçe ihtiyacımız var


2

Benim durumumda ContentProvider ve oda veritabanı birlikte çalışır, bu nedenle önce SqlLiteOpenHelper Sınıfını genişleten veritabanı sınıfı ile uygulamanın her yerinden ContentProvider'ın tüm geri çağrısını kaldırın.


2

Benim durumumda, geçiş içinde bir işlem kullanıyordum ve Oda, bir Geçiş Yardımcısı kullanarak karmayı güncelleyemedi

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

Birkaç saat uğraşıyorum ve çözüm buydu !! teşekkür ederim!!
Javier

1
Yukarıdaki örnekte sorun olan şey işlem değildir. İşlemi sonlandırmadan önce başarılı bir şekilde ayarlamayı unuttunuz: <pre> <code> database.beginTransaction () database.setTransactionSuccessful () database.endTransaction () </code> </pre>
birukoff

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

RoomDatabase sınıfınızdaki sürüm numarasını değiştirin. Sürüm numarasını artırın.


2

Şema sürümünü artırmak sizin için işe yaramadıysa, veritabanınızın geçişini sağlayın. Bunu yapmak için veritabanı oluşturucusunda geçişi bildirmeniz gerekir:

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

Evet bu uygun bir Yol
Bipin Bharti

1

Bir espresso testinde benzer bir sorun yaşadım ve bunu düzelten tek şey verileri temizlemek ve ayrıca androidx test uygulamalarını şöyle kaldırmaktı:

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

0

Benim durumumda, uygulamamla önceden paketleyeceğim bir veritabanında güncelleme yapıyordum. Buradaki önerilerin hiçbiri işe yaramadı. Ama sonunda .db dosyasını bir veritabanı programında açabileceğimi anladım ("SQLite için DB Browser" kullandım) ve "Kullanıcı sürümünü" 2'den 1'e manuel olarak değiştirebileceğimi anladım. Bundan sonra mükemmel çalıştı.

Sanırım herhangi bir güncelleme bu kullanıcı sürümünü değiştirirsiniz ve bu yüzden bu hatayı almaya devam ettim.


Bana aynı konuda yardım edebilir misin? SQLite için DB Tarayıcısında sürümü bulamıyorum
GreenROBO

"Pragmaları düzenle" sekmesinin altındadır. Adı "Kullanıcı Sürümü".
Gavin Wright

Evet. Anladım. Gavin yardım için teşekkürler :)
GreenROBO

-1

Benim durumumda yukarıdakilerin hepsini denedim. Hiçbir şey işe yaramadı, bu yüzden benim için çözüm basitçe ayarlamak android:allowBackup="false", uygulamayı yüklemek ve ardından doğru olarak

Umarım başkalarına yardımcı olur :)


1
Bu tam olarak cevapladığım şey, neden cevabı tekrarlayayım?
Divyanshu Negi

-2

Codelabs eğitim programı sırasında da aynı hatayı aldım. Nerede Bir eğitim oturumunda bir proje oluşturdum ve tüm veritabanı işlemleriyle başarılı bir şekilde çalıştı. Bir sonraki oturumda farklı bir repo ile çalışıyordum, ancak bu önceki projenin bir uzantısıydı, Genişletilmiş uygulamanın ilk sürümünden sadece hatayı aldım.

Belki Studio, yeni yapıda eksik olan oda veritabanıyla kimlik doğrulama tekniklerini korur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.