当前位置: 首页 > 知识库问答 >
问题:

拦截房间迁移错误以重新创建数据库

陶博赡
2023-03-14

https://medium . com/Google-developers/understanding-migrations-with-room-f01e 04 b 07929上有一篇关于房间迁移的很棒的文章

然而,我仍然错过了房间中的“灾难”恢复机制(例如,当发生异常情况时,将清除并重新创建数据库的fallbackToDestructiveRecreationOnMigrationError())

这是发生在我们身上的事

一个开发人员推出了带有迁移的版本9,但是模式9.json不一致(我不知道这怎么可能)

然后,当我们提供版本10时,文件9.json已更改=

我们必须告诉我们的用户擦除他们的数据(这不是一个技术问题,因为我们在应用程序启动时重新同步数据库,但这是一个公共关系问题)

我认为在构建器中使用openHelperFactory应该是可能的,但这对我来说还远未深入到房间内部

共有1个答案

邢杰
2023-03-14

经过多次尝试和绝望,这是我使用的解决方案:

abstract class MainDatabase: RoomDatabase() {
    companion object {
        val instance: MainDatabase by lazy {
            if (_instance == null) throw IllegalStateException("someone should have called init fun")
            _instance!!
        }

        private var _instance: MainDatabase? = null
        fun init(mainApplication: MainApplication) {
            _instance = init_(mainApplication)
            //force db opening and if it fails, we try to destroy and recreate the db
            try {
                _instance!!.openHelper.writableDatabase
            } catch (e: Exception) {
                Log.e("Database", "there was an error during DB opening => trying to destroy and recreate", e)
                _instance!!.openHelper.close()
                val dbPath = mainApplication.getDatabasePath(DB_NAME)
                if (SQLiteDatabase.deleteDatabase(dbPath)) {
                    _instance = init_(mainApplication)
                    _instance!!.openHelper.writableDatabase
                }
            }
        }

        private fun init_(mainApplication: MainApplication): MainDatabase {
            return Room.databaseBuilder(mainApplication, MainDatabase::class.java, DB_NAME)
                    .addMigrations(MIGRATION_1, MIGRATION_2, MIGRATION_3, MIGRATION_4, MIGRATION_5, MIGRATION_6, MIGRATION_7, MIGRATION_8, MIGRATION_9, MIGRATION_10)
                    .build()
        }
    }

这个解决方案的真正缺点是,对数据库的第一次访问是在主线程上完成的。。。

如果有人有更好的解决方案,请分享!

 类似资料:
  • 并且我发现了基于数据库版本4的可能场景的迁移varargs。 我的问题是,假设我使用的是db v1的Room,当我的应用程序到达db v10时,我将不得不编写多少迁移方法? 在sqlite中,我们在中获得已安装应用程序的当前db版本,我们只需通过开关大小写而不使用break语句,以便满足所有db升级。

  • 找到:TableInfo{name='news',Columns={alias=Column{name='alias',Type='text',affinity='2',notnull=false,PrimaryKeyPosition=0,DefaultValue='null'},Selected=Column{name='select',Type='integer',affinity='3',n

  • 最近,我决定将我的应用程序从Java重写为静态编程语言。问题是在房间中迁移会返回一个奇怪的异常。 这是我的数据类的一部分 注意:我自己没有更改列,因此我的迁移如下所示: 有人能告诉我为什么我看到而不是吗? 提前感谢!

  • 我在项目开发阶段。因此,我现在基本上不需要迁移。我以前有第一个表,第二个表是新添加的表。我已经预装了db。下面是使用的代码。 我还在AndroidManifest中给出了。xml。我不想使用,它也会清除我的预打包数据库。 我在emulator(API级别29)中卸载了该应用程序并运行了该应用程序。我得到了这个错误。 我不明白为什么重新安装会导致这个问题。有人能让我知道我做错了什么吗?

  • 已经创建了一个@Embedded类播放器。我想在其中添加ArrayList字段,该字段使用@TypeConverters,它在保存时将列表转换为Gson,在加载时将其转换为Gson。请告诉我如何在void migrate() 方法中请求将列表添加到Player类的现有实例中。 类保存: TypeConverter:

  • start-task 命令用于创建数据迁移任务。当数据迁移任务启动时,DM 将自动对相应权限和配置进行前置检查。 help start-task Starts a task as defined in the configuration file Usage: dmctl start-task [-s source ...] [--remove-meta] <config-file> [fla