A sala não pode verificar a integridade dos dados

105

Estou recebendo este erro ao executar o programa com Banco de Dados da Sala

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.

Parece que precisamos atualizar a versão do banco de dados, mas de onde podemos fazer isso na Room?

Ravi
fonte
2
Se você não se preocupa com os dados do aplicativo, excluir todo o conteúdo das configurações do aplicativo também pode ajudar, uma vez que destrói todo o banco de dados
O-9,

Respostas:

142

Ao se deparar com esta mensagem pela primeira vez, provavelmente você estará trabalhando em uma versão não lançada do banco de dados. Se for esse o caso, provavelmente você não deve incrementar a versão do banco de dados . Simplesmente limpar os dados do aplicativo fará com que você passe na exceção.

Se você não incrementar o banco de dados (recomendado):

Você deve limpar os dados do aplicativo do aplicativo das configurações do Android. Como alternativa, você pode desinstalar a versão anterior do aplicativo e, em seguida, instalar a nova versão para obter a exceção. Esta última abordagem não funciona sob certas condições (como quando permitir backup está ativado)

Já que limpar os dados do aplicativo sempre funciona, sempre faço esse caminho.

Se você incrementar a versão do banco de dados:

Você precisará escrever o código de migração do banco de dados para levar em conta quaisquer alterações no esquema do banco de dados. Veja aqui informações sobre migração.

A alternativa para escrever o código de migração do banco de dados é chamar fallbackToDestructiveMigrationo criador de banco de dados Room. Provavelmente não é uma boa ideia. Esquecer de remover esta chamada e depois esquecer de atualizar o banco de dados resultará em perda de dados.

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

Novamente, nem incrementar a versão do banco de dados, nem volta para a migração destrutiva caindo é necessário se o esquema do banco anterior não é viver em estado selvagem .

assinatura de método
fonte
4
Eu gostaria que eles incluíssem outro método substituto para este caso :(
BoD de
3
Na versão 1.0.0-rc1do Room, a única coisa que funcionou para mim foi incrementar a versão do banco de dados.
Dick Lucas
44
Eu tinha android: allowBackup = "true" no meu AndroidManifest.xml, o que evitou que os dados fossem apagados mesmo depois que o aplicativo foi desinstalado. Eu defini esse atributo como falso e reinstalei o aplicativo, o que ajudou a se livrar do problema. Observe que true é o valor padrão para allowBackup, portanto, se você não usá-lo, ele ainda pode fazer com que os dados sejam retidos.
Bartek
1
@Bartek este comentário agora merece ser uma resposta.
pistoleira
Que explicação! Eu estava desinstalando o aplicativo várias vezes porque por que atualizar a versão em desenvolvimento? Nossa, nunca pensei que limpar os dados das configurações é a chave para a frente. Boa resposta. Deve ser a solução aceita.
sud007
31

Por padrão, o manifesto do Android tem android:allowBackup="true", o que permite que os aplicativos persistam seu banco de dados SQLite na reinstalação.

Suponha que você DATABASE_VERSIONtenha inicialmente 3 e, em seguida, decida reduzir a versão do banco de dados de 3 para 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.
//        }
//    };
}

Você pode conseguir assim

  • Limpe os dados do aplicativo da configuração. Isso removerá o banco de dados mais antigo (DATABASE_VERSION = 3) do telefone
  • Desinstale seu aplicativo
  • Reduza DATABASE_VERSION versão para 1
  • Construir e reinstalar seu aplicativo

É uma boa prática mantê-lo DATABASE_VERSIONconstante.

Hitesh Sahu
fonte
1
Isso não afetará os usuários que atualizarão o aplicativo na Play Store?
nimi0112
1
Eu segui o mesmo caminho, mas não funcionou. Mesmo que eu esteja tentando instalar em um novo dispositivo do Android Studio, ele mostra o mesmo erro: x
Sadat
@ nimi0112 Para sua variante de lançamento, você deve permitir o backup, mas para sua variante de depuração, você pode desligá-lo
Chad Mx
27

android: allowBackup = "true" dentro de AndroidManifest.xml evita que os dados sejam apagados mesmo depois que o aplicativo for desinstalado.

Adicione isto ao seu manifesto:

android:allowBackup="false"

e reinstale o aplicativo.

Nota: Certifique-se de alterar de volta para verdadeiro mais tarde se desejar backups automáticos.

Outra solução:

Verifique o identityHash do seu arquivo json antigo e o novo arquivo json na pasta apps \ schema.

Se o identityHash for diferente, esse erro será gerado. Descubra o que você alterou comparando os dois arquivos json se não quiser alterar nada.

Certifique-se de ter exportSchema = true.

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

Arquivo de esquema json:

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

código:

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.");
    }
}
amor ao vivo
fonte
20

A resposta de Aniruddh Parihar me deu uma dica e resolveu.

Procure uma aula da qual você estendeu RoomDatabase. Lá você encontrará a versão abaixo:

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

basta aumentar a versão e o problema estará resolvido.

Ravi
fonte
12

É muito simples, conforme mostrado no 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.

Simplesmente vá para sua classe de versão de banco de dados e atualize sua versão de banco de dados aumentando 1 do atual.

Por exemplo: Encontre a anotação @Database em seu projeto como abaixo

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

Aqui versão = 1, é a versão do banco de dados, você tem que aumentar em um, é isso.

Aniruddh Parihar
fonte
1
Sim, recebi esse erro, é por isso que mencionei em questão também isso It seems we need to update database version. Mas eu não estava entendendo onde essa versão foi mencionada. De qualquer forma, obrigado por essa dica.
Ravi
Você reformulou a mensagem de erro, mas não forneceu nenhuma informação extra para resolver a confusão do autor da postagem original.
Carl Rossman de
@CarlRossman: Você tem que encontrar sua classe de banco de dados em seu projeto onde você usou a anotação de banco de dados, nessa classe você encontrará a versão do banco de dados (valor inteiro), apenas aumente em um do atual.
Aniruddh Parihar de
7

1: - Parece que precisamos atualizar a versão do banco de dados (incremento em 1)

insira a descrição da imagem aqui

Desinstale o aplicativo ou limpe os dados do aplicativo

Keshav Gera
fonte
6

No telefone Android:

Desinstale o aplicativo ou limpe os dados do aplicativo

Para excluir dados de aplicativos: Vá para configurações -> Aplicativos -> Selecione seu aplicativo -> Armazenamento -> Limpar dados

A desinstalação (e reinstalação) não funciona em todos os casos, então tente limpar os dados primeiro!

Marci
fonte
Sim, funcionou. Mas estranhamente, eu estava pegando esse problema em um dispositivo que foi totalmente apagado e configurado do zero agora. Mas simplesmente limpar os dados resolvidos.
Ajith Memana
Isso não deve ser feito na produção. Você não deve forçar todos os seus usuários a limpar os dados do aplicativo. Melhor escrever o código de migração aumentando a versão em 1 no banco de dados da Room.
Rajeev Jayaswal
5

No meu caso, android:allowBackup="false"mudar de verdadeiro para falso funcionou, já que isso também me deu pesadelos antes, essa é a coisa mais estranha por que essa configuração está habilitada por padrão!

Divyanshu Negi
fonte
5

Para corrigir o problema no kotlin:

Primeiro

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

Segundo

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

Terceiro

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

Para mais detalhes, verifique a documentação oficial

Peterzinho16
fonte
4

Esse problema ocorre principalmente no desenvolvimento.

Se você alterar seu esquema, ou seja, renomear / adicionar / modificar sua classe que contém a entidade de tabela, a integridade entre a saída do banco de dados em sua construção anterior entra em conflito com a nova construção.

limpe os dados do aplicativo ou instale uma nova compilação após desinstalar a compilação anterior .

Agora, o banco de dados antigo não entrará em conflito com o mais recente.

Extremis II
fonte
Depois disso, ainda há falha
user7856586
qual é a exceção? por favor, coloque o log para restringir o problema.
Extremis II
2
Obrigado, está tudo bem agora. Eu li sobre android:allowBackup="true"e usei com sabedoria
user7856586
1
@ user7856586 E quanto a allowBackup? Você poderia nos iluminar com sua sabedoria?
Ridcully
@Ridcully você pode ler sobre isso aqui Por que você está tão bravo?
user7856586
3

No meu caso, eu estava usando uma transação dentro da migração e a Room não conseguiu atualizar o hash usando um Migration Helper

@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() 
}
JARP
fonte
Luto por várias horas e essa foi a solução !! obrigado!!
Javier
1
No exemplo acima, não é a transação que é um problema. Você esqueceu de definir a transação com êxito antes de encerrá-la: <pre> <code> database.beginTransaction () database.setTransactionSuccessful () database.endTransaction () </code> </pre>
birukoff
3

No meu caso, tive uma classe AppDatabase.

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

Atualizei este número de versão e resolveu o problema. O problema surgiu porque eu adicionei uma propriedade na classe SongInfo e esqueci de atualizar o número da versão.

Espero que ajude alguém.

Harry .Naeem
fonte
2

Se você estiver atualizando a versão do Room para 1.0.0-alpha9 da versão antiga, visite o artigo abaixo. Artigo muito bom para migrar da versão antiga para a versão 1.0.0-alpha9.

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

Na nova versão da Room 1.0.0-alpha9, a Room adiciona suporte para a restrição NOT NULL.

Isso vai mudar o esquema gerado pelo Room. Como ele muda o esquema, ele também muda o identityHash do banco de dados e que é usado pela Room para identificar exclusivamente cada versão do banco de dados. Portanto, precisamos de uma migração

Bhargav Pandya
fonte
2

No meu caso, o ContentProvider e o banco de dados da sala trabalham juntos, portanto, primeiro remova todos os retornos de chamada de ContentProvider em todo o aplicativo com a classe de banco de dados que estende a classe SqlLiteOpenHelper

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

Altere o número da versão em sua classe RoomDatabase. Aumente o número da versão.

Rajeev Shetty
fonte
2

Se aumentar a versão do esquema não funcionou com você, forneça a migração do seu banco de dados. Para fazer isso, você precisa declarar a migração no construtor de banco de dados:

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");
    }
};
Hagar Magdy
fonte
Sim, este é o caminho adequado
Bipin Bharti
1

Acabei de ter um problema semelhante em um teste do espresso e a única coisa que corrigiu foi limpar os dados e também desinstalar os apks de teste do androidx como:

adb uninstall androidx.test.orchestrator
adb uninstall androidx.test.services
Daniel Jonker
fonte
0

No meu caso, tentei todas as opções acima. Nada parecia trabalho para que a solução para mim foi simplesmente definindo android:allowBackup="false", instalar o aplicativo, em seguida, configurá-lo de volta à realidade

Espero que ajude outras pessoas :)

gmartinsnull
fonte
1
Isso é exatamente o que eu respondi, por que repetir a resposta?
Divyanshu Negi
0

No meu caso, eu estava atualizando um banco de dados que irei pré-empacotar com meu aplicativo. Nenhuma das sugestões aqui funcionou. Mas finalmente descobri que poderia abrir o arquivo .db em um programa de banco de dados (usei "DB Browser for SQLite") e alterar manualmente a "Versão do usuário" de 2 para 1. Depois disso, funcionou perfeitamente.

Acho que qualquer atualização que você fizer altera a versão do usuário, e é por isso que continuo recebendo esse erro.

Gavin Wright
fonte
Você pode me ajudar com o mesmo? Não consigo encontrar a versão no DB Browser para SQLite
GreenROBO
Está na guia "Editar pragmas". É chamado de "Versão do usuário".
Gavin Wright de
Sim. Deixa comigo. Obrigado pela ajuda Gavin :)
GreenROBO
-2

Recebi o mesmo erro durante o programa de treinamento do Codelabs. Onde Em uma sessão de treinamento eu criei um projeto e ele foi executado com sucesso com todas as operações de banco de dados. Na próxima sessão, eu estava trabalhando com um repo diferente, mas era uma extensão do projeto anterior. Somente da primeira construção do aplicativo estendido eu recebi o erro.

Talvez o Studio mantenha técnicas de autenticação com o banco de dados de salas que está faltando na nova construção.

Willey Hute
fonte