Попытка комнаты повторно открыть уже закрытую базу данных

При использовании Room из компонентов архитектуры Android я получил следующую ошибку при попытке доступа к базе данных с помощью компонента 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 после инициализации базы данных и внедрения ее в мой класс.


person huw    schedule 28.07.2017    source источник


Ответы (3)


Это потому, что вы пытаетесь изменить схему существующей базы данных, не сообщая ей никакой информации о миграции. Таким образом, в основном он пытается записать новую схему базы данных в существующую БД, которая не работает.

Есть два способа обойти это. Если вы находитесь в своей среде разработки, вы можете вернуться к деструктивной миграции, для этого ваш код создания базы данных будет выглядеть примерно так:

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

Это означает, что когда вы предоставляете базе данных обновленный или новый объект, она будет делать то, что сказал ответ @huw, и просто удаляет базу данных при установке приложения, удаляя из нее все данные, и дает вам новую установку.

Другой метод заключается в использовании функции миграции. Они довольно длинные, поэтому, если кто-то не хочет, чтобы я написал это здесь, я пока оставлю это, но в основном документацию можно найти здесь:

Документация по миграции БД Room

По сути, это заставляет БД запускать некоторый SQL, предоставленный вами, для обновления базы данных до новой версии. Таким образом, вы можете гарантировать, что ни одна из ваших данных не будет потеряна во время миграции; или как можно меньше в зависимости от того, что вы делаете. Это предпочтительный метод для рабочих приложений, поскольку он означает, что пользователи не потеряют свои ранее существовавшие данные, и вы не получите много гневных отзывов/потерянных клиентов.

Надеюсь, это поможет!

person James Lendrem    schedule 07.09.2017
comment
Не забудьте изменить версию базы данных в аннотации @Database. fallbackToDestructiveMigration() не будет сбрасывать БД только потому, что структура БД изменена. - person Andrew; 05.12.2017
comment
Я знаю, что это немного поздно, но кто-то, у кого все еще есть такая же проблема, может обратиться к проблеме GitHub ниже. github.com/googlesamples/android-architecture-components/issues/ - person Ilanthirayan Paramanathan; 20.12.2018
comment
Я предоставил информацию о миграции, но все равно получил ошибку! .PDatabase$Companion$MIGRATION_3_4$1.migrate (PDatabase.java:195) - person Dr.jacky; 06.01.2021

Одним из решений этой проблемы было удаление файла базы данных и запуск заново. Это не было проблемой, так как я только тестировал и мог повторно заполнить базу данных, используя онлайн-данные.

Для этого:

  • Информация о приложении > Хранилище > Очистить данные
  • Вручную удалить файл в /data/data/com.app.example/databases/database.db
person huw    schedule 28.07.2017
comment
Путь /data/data/.... не доступен напрямую для устройства Android, для доступа к этому пути к файлу должно быть установлено корневое устройство. - person Jayesh; 16.08.2018
comment
Правильно — я разрабатывал на рутованном устройстве, так что у меня это сработало. (Не уверен, но вы также можете сделать это через adb?) - person huw; 16.08.2018

У меня было такое исключение после не очень успешной миграции. Всегда дважды проверяйте SQL-запрос, который вы используете для миграции. Вы можете создать новый столбец с неправильным типом данных, и описание исключения не поможет.

person lomza    schedule 05.04.2018