使用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访问数据库时都会发生此错误。
答案 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查询。您可以使用错误的数据类型创建新列,但例外情况的说明不会有帮助。