Home > Software design >  Room db migration fallbackToDestructiveMigration() not working
Room db migration fallbackToDestructiveMigration() not working

Time:09-28

I am using Room with a prepopulated database in the assets folder. For an app update, I would like to alter this database by adding a new column and prepopulating this column with new data.

The database was auto-migrated from version 1 to 2 (a table was added). From version 2 to 3, I would now like to apply abovementioned changes by providing a different 'database.db' file in the assets folder and allowing for destructive migration.

@Database(entities = [Object1::class, Object2::class], version = 3, autoMigrations = [
    AutoMigration (from = 1, to = 2)], exportSchema = true)
abstract class AppDatabase : RoomDatabase() {

    abstract fun dao(): Dao

    companion object {

        private const val DB_NAME = "database.db"

        @Volatile
        private var instance: AppDatabase? = null

        fun getInstance(context: Context): AppDatabase {
            return instance ?: synchronized(this) {
                instance ?: buildDatabase(context).also { instance = it }
            }
        }

        private fun buildDatabase(context: Context): AppDatabase {
            return Room.databaseBuilder(
                context,
                AppDatabase::class.java, "AppDB.db")
                .fallbackToDestructiveMigration()
                .createFromAsset(DB_NAME)
                .build()
        }
    }
}

The problem is that I still get the following exception:

   java.lang.IllegalStateException: A migration from 1 to 3 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.

I am unsure why this would still happen. I thought it was either providing a migration script or allowing for destructive migration that makes the migration work.

Added Comment:-

I have tried an implemented migration, but the same exception as above happened again. When I try starting over with versionCode 1, I am getting "java.lang.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." I have also changed the database name and added android:allowBackup="false" in the manifest.

Any ideas?

CodePudding user response:

Digging through the room documentation doesn't turn much up, my hunch is that it has to do with the fact that you are using Automigrations instead of implemented migrations. Have you tried changing that Automigration from 1->2 to an implemented migration?

Also, since you are manually replacing it with a new database that has prepopulated data my solution would be to just get rid of the old migrations, change the name of the DB slightly and start over from version 1. There's no reason to maintain the old migrations if anyone going from older versions to the current version are having their DB deleted.

CodePudding user response:

I believe that your issue may be with the pre-populated database, in that it's version number (user_version) hasn't been changed to 3.

  • you can change the version using the SQL (from an SQlite tool ) PRAGMA user_version = 3;

The documentation says :-

Here is what happens in this situation:

  • Because the database defined in your app is on version 3 and the database instance already installed on the device is on version 2, a migration is necessary.
  • Because there is no implemented migration plan from version 2 to version 3, the migration is a fallback migration.
  • Because the fallbackToDestructiveMigration() builder method is called, the fallback migration is destructive. Room drops the database instance that's installed on the device.
  • Because there is a prepackaged database file that is on version 3, Room recreates the database and populates it using the contents of the prepackaged database file.
    • If, on the other hand, you prepackaged database file were on version 2, then Room would note that it does not match the target version and would not use it as part of the fallback migration.
  • By note perhaps by the way of an exception?
  • Related