房间试图重新打开已经关闭的数据库

时间:2017-07-28 14:50:12

标签: android android-room android-architecture-components

使用Android架构组件中的Room时,在尝试使用Dagger组件访问数据库时收到以下错误:

java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: (database path)

我使用的是Dagger版本2.11和Room版本1.0.0-alpha7。该错误在版本1.0.0-alpha5上可重现。

在初始化数据库并将其注入我的类后,任何尝试通过DAO访问数据库时都会发生此错误。

3 个答案:

答案 0 :(得分:76)

这是因为您尝试修改现有数据库的架构而不向其提供任何迁移信息。所以基本上它会尝试将新的数据库模式编写到现有的数据库中,但不起作用。

有两种解决方法。如果您在开发环境中,那么您可以做的就是回退到破坏性迁移,为此,您的数据库创建代码将如下所示:

MyDatabase myDatabase = Room.databaseBuilder(context, MyDatabase.class, "my-db")
    .fallbackToDestructiveMigration()
    .build();

这意味着当您为数据库提供更新或新实体时,它将执行@huw所说的答案,并删除应用程序安装中的数据库,从中删除所有数据并给您一个新的安装。

另一种方法是使用迁移功能。它们很长,所以除非有人要我在这里写,我现在就把它留下来,但基本上,文档可以在这里找到:

Room DB Migration Documentation

这实质上导致DB运行自己提供的一些SQL来将数据库更新到新版本。这样,您可以确保在执行迁移时不会丢失任何数据;或尽可能少,取决于你在做什么。这是生产应用程序的首选方法,因为这意味着用户不会丢失已有的数据,并且您不会获得大量愤怒的评论/失去的客户。

希望有所帮助!

答案 1 :(得分:15)

此问题的一个解决方案是删除数据库文件并重新开始。这不是问题,因为我只是在测试,可以使用在线数据重新填充数据库。

要么这样做:

  • 应用信息>存储>清除数据
  • /data/data/com.app.example/databases/database.db
  • 手动删除文件

答案 2 :(得分:0)

在没有如此成功的迁移之后,我遇到了这种异常。始终仔细检查用于迁移的SQL查询。您可以使用错误的数据类型创建新列,但例外情况的说明不会有帮助。