android – Please provide a Migration in the builder or call fallbackToDestructiveMigration in the builder in which case Room will re-create all of the tables-ThrowExceptions

Exception or error:

I am using Room With RxJava2. I added a column in my table so I am migrating to new version. I have changed my Database version to 2.

Following is my migration code

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("ALTER TABLE users "
        +"ADD COLUMN address String");

    }
};

AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, DB_NAME)
.addMigrations(MIGRATION_1_2)
.build();

If you want to see the full code,
I am refering to this example on Github, it does not have the migration code

https://github.com/alahammad/RoomSample

I am following the steps described in the documentation but still my app crashes.

Error Logs

Process: demo.karaoke.sensibol.com.roomrajava2, PID: 13655
    io.reactivex.exceptions.OnErrorNotImplementedException: A migration from 1 to 2 is necessary. Please provide a Migration in the builder or call fallbackToDestructiveMigration in the builder in which case Room will re-create all of the tables.
        at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704)
        at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701)
        at io.reactivex.internal.operators.maybe.MaybeCallbackObserver.onError(MaybeCallbackObserver.java:83)
        at io.reactivex.internal.operators.maybe.MaybeObserveOn$ObserveOnMaybeObserver.run(MaybeObserveOn.java:99)
        at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
        at android.os.Handler.handleCallback(Handler.java:815)
        at android.os.Handler.dispatchMessage(Handler.java:104)
        at android.os.Looper.loop(Looper.java:194)
        at android.app.ActivityThread.main(ActivityThread.java:5643)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
     Caused by: java.lang.IllegalStateException: A migration from 1 to 2 is necessary. Please provide a Migration in the builder or call fallbackToDestructiveMigration in the builder in which case Room will re-create all of the tables.
        at android.arch.persistence.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:82)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onUpgrade(FrameworkSQLiteOpenHelper.java:118)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:256)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:93)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:54)
        at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:193)
        at demo.karaoke.sensibol.com.roomrajava2.UserDao_Impl$4.call(UserDao_Impl.java:137)
        at demo.karaoke.sensibol.com.roomrajava2.UserDao_Impl$4.call(UserDao_Impl.java:135)
        at io.reactivex.internal.operators.maybe.MaybeFromCallable.subscribeActual(MaybeFromCallable.java:46)
        at io.reactivex.Maybe.subscribe(Maybe.java:3749)
        at io.reactivex.internal.operators.maybe.MaybeSubscribeOn$SubscribeTask.run(MaybeSubscribeOn.java:54)
        at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:452)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:818)
How to solve:

I ran your app from GitHub and made a sample migration from ver 1 to ver 2. It turns our there’s a mistake in SQL query. It should be:

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("ALTER TABLE users "
        +"ADD COLUMN address TEXT");

    }
};

String > TEXT

It’s also preferable to make Room’s database instance a singleton, and use it only in Repo/CacheManager class. Please check the gist for a complete code changes – https://gist.github.com/lomza/0f311a1b1e9c896bc58dff925d65eab2

###

add “.fallbackToDestructiveMigration()” before build(),

###

If you don’t want to provide migrations and you specifically want your database to be cleared when you upgrade the version, call fallbackToDestructiveMigration in the database builder

database = Room.databaseBuilder(context.getApplicationContext(),
                    UsersDatabase.class, "Sample.db")
            .fallbackToDestructiveMigration()
            .build();

###

Clear the app data and uninstall then install it again , it will work. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *