Search code examples
androidkotlinandroid-roomdatabase-migration

Room db migration fallbackToDestructiveMigration() not working


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?


Solution

  • I finally figured out what the problem was, it had nothing to do with the versioning or anything else related to room or the asset db file.

    It was dependency injection.

    I provided my database to Dagger in a DatabaseModule class as follows:

    private const val DB_NAME = "database.db"
    
    @InstallIn(SingletonComponent::class)
    @Module
    class DatabaseModule {
    
    @Provides
    fun provideDao(appDatabase: AppDatabase): Dao {
        return appDatabase.dao()
    }
    
    @Provides
    @Singleton
    fun provideAppDatabase(@ApplicationContext appContext: Context): AppDatabase {
        return Room.databaseBuilder(
            appContext,
            AppDatabase::class.java, "AppDB.db")
            .createFromAsset(DB_NAME)
            .build()
    }
    

    }

    It was missing the fallBackToDestructiveMigration() call, so this messed up Room's internal onUpgrade call in RoomOpenHelper.java.

    To fix it, I made my buildDatabase call in AppDatabase public and used it to provide the database to Dagger in the DatabaseModule class.