【问题标题】:Please provide a Migration in the builder or call fallbackToDestructiveMigration in the builder in which case Room will re-create all of the tables请在构建器中提供迁移或在构建器中调用 fallbackToDestructiveMigration,在这种情况下,Room 将重新创建所有表
【发布时间】:2018-04-03 12:04:25
【问题描述】:

我正在使用带有 RxJava2 的 Room。我在表中添加了一个列,因此我正在迁移到新版本。我已将数据库版本更改为 2。

以下是我的迁移代码

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();

如果您想查看完整代码, 我指的是 Github 上的这个例子,它没有迁移代码

https://github.com/alahammad/RoomSample

我正在按照文档中描述的步骤操作,但我的应用仍然崩溃。

错误日志

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)

【问题讨论】:

  • 能否添加错误日志
  • @AmjadKhan 我已经添加了错误日志,请查看
  • 您是否在 AppDatabase 类中添加了 @Database(entities = {}, version = 1) 注释?您是否在手机上安装了版本 1,然后使用迁移和版本 = 2 更新了代码并尝试安装?
  • @lomza 是的,我做到了。对于版本 1 @Database(entities = {User.class}, version = 1),我在手机上安装了该应用程序,然后我添加了一列并更改了 @Database(entities = {User.class}, version = 2) 和再次在我的手机上安装了该应用
  • 有一篇关于迁移的好文章 - medium.com/google-developers/… 也许你会在那里找到解决方案...

标签: android android-room


【解决方案1】:

如果您不想提供迁移,并且特别希望在升级版本时清除数据库,请在数据库构建器中调用 fallbackToDestructiveMigration

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

【讨论】:

  • 我们需要更新数据库版本还是保持原样?
  • 迁移发生在数据库更改时,因此您需要升级数据库版本。这可以帮助你medium.com/androiddevelopers/…@KishanSolanki
  • fallbackTODestructiveMigration 每次新建或关闭所有并重新启动应用程序时都会清理我的数据库。使用这个临时的迁移
【解决方案2】:

在 build() 之前添加“.fallbackToDestructiveMigration()”,

【讨论】:

  • ...仅当您希望您的用户丢失所有保存的数据时
  • @smitty1。同意。我还怀疑当程序员以后想要添加迁移时,他会遇到从旧版本迁移的问题。
【解决方案3】:

我从 GitHub 运行了您的应用程序,并进行了从版本 1 到版本 2 的示例迁移。结果发现 SQL 查询中存在错误。应该是:

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");

    }
};

字符串 > 文本

最好将 Room 的数据库实例设为单例,并仅在 Repo/CacheManager 类中使用它。请检查要点以获取完整的代码更改 - https://gist.github.com/lomza/0f311a1b1e9c896bc58dff925d65eab2

【讨论】:

  • 感谢您的回答。让我检查并回复你。你花时间检查我的代码对我来说真的很重要。欣赏它
  • 即使我写的是字符串而不是文本,它也能工作。问题出在我在 gist.github.com/lomza/0f311a1b1e9c896bc58dff925d65eab2 中提供的 Singleton 类中
【解决方案4】:

如果可以接受丢失现有数据,请在创建数据库时调用fallbackToDestructiveMigration() builder 方法

示例:

db = Room.databaseBuilder(getApplicationContext(),
                    User.class, "DB_Name")
            .fallbackToDestructiveMigration()
            .build();

【讨论】:

    【解决方案5】:

    在 build() 之前添加“.fallbackToDestructiveMigration()”, 并且还增加了为我固定的版本号。希望它为搜索的人修复。在这里。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      • 2016-09-04
      • 2020-04-03
      • 1970-01-01
      • 2019-08-18
      相关资源
      最近更新 更多