Room no puede verificar la integridad de los datos

92

Recibo este error al ejecutar el programa con 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.

Parece que necesitamos actualizar la versión de la base de datos, pero ¿desde dónde podemos hacerlo en Room?

Ravi
fuente
2
Si no le importan los datos de la aplicación, eliminar todo el contenido de la configuración de la aplicación también podría ayudar, ya que simplemente destruye toda la base de datos
O-9

Respuestas:

131

Cuando se encuentre con este mensaje por primera vez, lo más probable es que esté trabajando con una versión inédita de la base de datos. Si ese es el caso, lo más probable es que no deba incrementar la versión de la base de datos . Con solo borrar los datos de la aplicación, pasará la excepción.

Si no incrementa la base de datos (recomendado):

Debe borrar los datos de la aplicación de la aplicación de la configuración de Android. Alternativamente, podría desinstalar la versión anterior de la aplicación y luego instalar la nueva versión para pasar la excepción. Este último enfoque no funciona bajo ciertas condiciones (como cuando la opción Permitir copia de seguridad está habilitada)

Dado que la limpieza de los datos de la aplicación siempre funciona, siempre tomo esa ruta.

Si incrementa la versión de la base de datos:

Deberá escribir el código de migración de la base de datos para tener en cuenta los cambios en el esquema de la base de datos. Consulte aquí para obtener información sobre la migración.

Una alternativa a escribir el código de migración de la base de datos es llamar fallbackToDestructiveMigrational generador de base de datos de Room. Probablemente no sea una buena idea. Olvidar eliminar esta llamada y luego olvidar actualizar la base de datos resultará en la pérdida de datos.

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

Nuevamente, no es necesario incrementar la versión de la base de datos ni recurrir a la migración destructiva si el esquema de base de datos anterior no está activo .

método firma
fuente
4
Me gustaría que incluyeran otro método alternativo para este caso :(
BoD
3
En la versión 1.0.0-rc1de Room, lo único que funcionó para mí fue incrementar la versión de la base de datos.
Dick Lucas
42
Tenía android: allowBackup = "true" en mi AndroidManifest.xml que impedía que los datos se borraran incluso después de desinstalar la aplicación. Configuré este atributo en falso y luego reinstalé la aplicación, lo que ayudó a solucionar el problema. Tenga en cuenta que true es el valor predeterminado para allowBackup, por lo que si no lo usa en absoluto, aún podría hacer que se retengan los datos.
Bartek
1
@Bartek este comentario ahora merece ser una respuesta.
guness
¡Qué explicación! Desinstalaba la aplicación una y otra vez porque ¿por qué actualizar la versión en desarrollo? Vaya, nunca pensé que borrar los datos de la configuración fuera la clave. Buena respuesta. Debería ser la solución aceptada.
sud007
29

Por defecto, el manifiesto de Android tiene android:allowBackup="true", lo que permite que las aplicaciones conserven su base de datos SQLite en la reinstalación.

Suponga que DATABASE_VERSIONinicialmente era 3 y luego decide reducir la versión de base de datos de 3 a 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.
//        }
//    };
}

Puedes lograrlo así

  • Borrar datos de la aplicación de Configuración. Esto eliminará la base de datos más antigua (DATABASE_VERSION = 3) del teléfono
  • Desinstale su aplicación
  • Reducir la versión de DATABASE_VERSION a 1
  • Cree y reinstale su aplicación

Es una buena práctica mantenerlo DATABASE_VERSIONconstante.

Hitesh Sahu
fuente
1
¿No afectará a los usuarios que actualizarán la aplicación desde Play Store?
nimi0112
1
Seguí el mismo camino, pero no funcionó. Incluso estoy intentando instalar en un dispositivo nuevo de Android Studio, muestra el mismo error: x
Sadat
@ nimi0112 Para su variante de lanzamiento, debe permitir la copia de seguridad, sin embargo, para su variante de depuración, puede desactivarlo
Chad Mx
25

android: allowBackup = "true" dentro de AndroidManifest.xml evita que los datos se borren incluso después de desinstalar la aplicación.

Agregue esto a su manifiesto:

android:allowBackup="false"

y reinstale la aplicación.

Nota: asegúrese de volver a cambiarlo a verdadero más adelante si desea realizar copias de seguridad automáticas.

Otra solución:

Verifique la identidadHash de su antiguo archivo json y el nuevo archivo json en la carpeta apps \ schema.

Si el identityHash es diferente, dará ese error. Descubra lo que ha cambiado comparando ambos archivos json si no desea cambiar nada.

Asegúrese de tener exportSchema = true.

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

archivo 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.");
    }
}
vive el amor
fuente
19

La respuesta de Aniruddh Parihar me dio una pista y se resolvió.

Busque una clase en la que se haya extendido RoomDatabase. Allí encontrará una versión como la siguiente:

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

simplemente aumente la versión y el problema está resuelto.

Ravi
fuente
12

Es muy simple como se muestra en el registro

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

Simplemente vaya a la clase Versión de base de datos y actualice su versión de base de datos aumentando 1 desde la actual.

Aniruddh Parihar
fuente
1
Sí, obtuve ese error, por eso también lo mencioné en la pregunta It seems we need to update database version. Pero no estaba llegando a donde se mencionó esa versión. De todos modos gracias por esa pista.
Ravi
7

1: - Parece que necesitamos actualizar la versión de la base de datos (incrementar en 1)

ingrese la descripción de la imagen aquí

2.o Desinstale la aplicación o borre los datos de la aplicación

Keshav Gera
fuente
6

En un teléfono Android:

Desinstalar la aplicación o borrar los datos de la aplicación

Para eliminar los datos de la aplicación: vaya a Configuración -> Aplicaciones -> Seleccione su aplicación -> Almacenamiento -> Borrar datos

La desinstalación (y reinstalación) no funciona en todos los casos, ¡así que intente borrar los datos primero!

Marci
fuente
Sí, eso funcionó. Pero, curiosamente, recibí este problema en un dispositivo que se borró por completo y se configuró de nuevo. Pero simplemente borrando los datos resuelto.
Ajith Memana
Esto no debe hacerse en producción. No debe obligar a todos sus usuarios a borrar datos de la aplicación. Es mejor escribir código de migración aumentando la versión en 1 en su base de datos de Room.
Rajeev Jayaswal
5

En mi caso, android:allowBackup="false"hacerlo de verdadero a falso funcionó, ya que esto también me ha dado pesadillas antes, ¡esto es lo más extraño por qué esta configuración está habilitada de forma predeterminada!

Divyanshu Negi
fuente
5

Para solucionar el problema en kotlin:

primero

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

Tercero

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

Para más detalles, consulte la documentación oficial.

peterzinho16
fuente
4

Este problema ocurre principalmente en el desarrollo.

Si cambia su esquema, es decir, cambie el nombre / agregue / modifique su clase que contiene la entidad de tabla, la integridad entre la salida de db en su compilación anterior entra en conflicto con la nueva compilación.

borre los datos de la aplicación o instale una nueva compilación después de desinstalar la compilación anterior .

Ahora, la antigua base de datos no entrará en conflicto con la más nueva.

Extremis II
fuente
Después de eso, todavía se
bloquea
cual es la excepcion? por favor coloque el registro para delimitar el problema.
Extremis II
2
Gracias, todo está bien ahora. Lo leí android:allowBackup="true"y lo uso sabiamente
user7856586
1
@ user7856586 Entonces, ¿qué pasa con allowBackup? ¿Podrías iluminarnos con tu sabiduría?
Ridcully
@Ridcully, puedes leer sobre eso aquí. ¿Por qué estás tan enojado?
user7856586
3

En mi caso, tenía una clase AppDatabase.

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

Actualicé este número de versión y resolvió el problema. El problema surgió porque había agregado una propiedad en la clase SongInfo y olvidé actualizar el número de versión.

Espero que ayude a alguien.

Harry .Naeem
fuente
2

Si está actualizando la versión de Room a 1.0.0-alpha9 desde la versión anterior, visite el artículo a continuación. Muy buen artículo para migrar de la versión anterior a la versión 1.0.0-alpha9.

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

In Room New Version 1.0.0-alpha9 Room agrega soporte para la restricción NOT NULL.

Eso va a cambiar el esquema que genera Room. Debido a que cambia el esquema, también cambia el identityHash de la base de datos y que Room utiliza para identificar de forma única cada versión de la base de datos. Por tanto, necesitamos una migración

Bhargav Pandya
fuente
2

En mi caso, ContentProvider y la base de datos de la sala funcionan juntas, así que primero elimine todas las devoluciones de llamada de ContentProvider en toda la aplicación con la clase de base de datos que extiende la clase SqlLiteOpenHelper

chaman
fuente
2

En mi caso, estaba usando una transacción dentro de la migración y Room no pudo actualizar el hash usando un Asistente de migración

@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
fuente
¡¡Lucho por varias horas y esta fue la solución !! ¡¡gracias!!
Javier
1
En el ejemplo anterior, no es la transacción la que es un problema. Olvidó configurar la transacción correctamente antes de finalizarla: <pre> <code> database.beginTransaction () database.setTransactionSuccessful () database.endTransaction () </code> </pre>
birukoff
2
@Database(entities = {Tablename1.class, Tablename2.class}, version = 3, exportSchema = false)

Cambie el número de versión en su clase RoomDatabase. Incrementa el número de versión.

Rajeev Shetty
fuente
2

Si aumentar la versión del esquema no funcionó con usted, proporcione la migración de su base de datos. Para hacerlo, debe declarar la migración en el generador de bases de datos:

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
fuente
Sí, esta es la manera correcta
Bipin Bharti
1

Acabo de tener un problema similar en una prueba de espresso y lo único que lo solucionó fue borrar datos y también desinstalar las aplicaciones de prueba de androidx como:

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

En mi caso, estaba actualizando una base de datos que empacaré previamente con mi aplicación. Ninguna de las sugerencias aquí funcionó. Pero finalmente me di cuenta de que podía abrir el archivo .db en un programa de base de datos (usé "DB Browser para SQLite") y cambiar manualmente la "Versión de usuario" de 2 a 1. Después de eso, funcionó perfectamente.

Supongo que cualquier actualización que realice cambia esta versión de usuario, y es por eso que seguí recibiendo este error.

Gavin Wright
fuente
¿Puedes ayudarme con lo mismo? No puedo encontrar la versión en DB Browser para SQLite
GreenROBO
Está en la pestaña "Editar pragmas". Se llama "Versión de usuario".
Gavin Wright
Si. Lo tengo. Gracias por la ayuda Gavin :)
GreenROBO
-1

En mi caso probé todo lo anterior. Nada parecía funcionar, así que la solución para mí fue simplemente configurar android:allowBackup="false", instalar la aplicación y luego volver a configurarla en verdadero

Espero que ayude a otros :)

gmartinsnull
fuente
1
Esto es exactamente lo que he respondido, ¿por qué repetir la respuesta?
Divyanshu Negi
-2

Recibí el mismo error durante el programa de capacitación de Codelabs. Donde En una sesión de entrenamiento creé un proyecto y funcionó exitosamente con todas las operaciones de la base de datos. En la siguiente sesión, estaba trabajando con un repositorio diferente, pero era una extensión del proyecto anterior. Desde la primera compilación de la aplicación extendida, solo yo tenía el error.

Tal vez Studio mantenga las técnicas de autenticación con la base de datos de habitaciones que falta con la nueva construcción.

Shrinivas Manjithaya
fuente