Intereting Posts

Попытка написать базу данных только для чтения … но я не

У меня есть соединение с базой данных только для чтения. Иногда при чтении данных из базы данных с помощью запроса SELECT он SQLiteReadOnlyDatabaseException .

Я открываю соединение следующим образом:

 return SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY); 

Запрос:

 Select * FROM BudgetVersions WHERE entityId = ? 

Я читаю данные из базы данных с помощью db.rawQuery() , например:

 String query = ...; Cursor c = db.rawQuery(query, new String[]{ activeBudgetId }); try { if (c.moveToFirst()) { bv.versionName = c.getString(c.getColumnIndexOrThrow("versionName")); return bv; } else { return null; } } finally { c.close(); } 

Очень редко, я получаю такой крах, внутри вызова c.moveToFirst() :

 Caused by: android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 776) at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method) at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:845) at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836) at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62) at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:144) at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133) at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197) at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237) 

В качестве обходного пути я мог бы попытаться использовать доступное для записи соединение с базой данных, но я хотел бы знать, почему происходит сбой.

Таблица, которую я читаю, представляет собой стандартную таблицу SQLite:

 CREATE TABLE BudgetVersions ( entityId VARCHAR PRIMARY KEY NOT NULL UNIQUE, budgetId VARCHAR NOT NULL, versionName VARCHAR NOT NULL, dateFormat VARCHAR, currencyFormat VARCHAR, lastAccessedOn DATETIME, isTombstone BOOL NOT NULL, deviceKnowledge NUMERIC NOT NULL ); 

Я видел, что авария произошла как на эмуляторе KitKat, так и на устройстве с Lollipop.


Одновременно доступно отдельное записываемое соединение, открытое для одной базы данных, принадлежащее WebView. База данных обновляется кодом Javascript в WebView и читается на собственном уровне Android / Java с помощью этого подключения только для чтения.

Я ожидаю, что это может оказаться основной причиной проблемы, но я хотел бы подробно разобраться, почему соединение только для чтения будет мешать отдельному записываемому соединению.

Мне хорошо известно, что общий совет – использовать одно соединение с базой данных, но поскольку доступное для записи соединение принадлежит WebView , у меня нет простого доступа к нему из кода Java.

Solutions Collecting From Web of "Попытка написать базу данных только для чтения … но я не"

Решено, изменив его на доступное для записи соединение с базой данных. Подсказка была в документации для кода ошибки 776 :

(776) SQLITE_READONLY_ROLLBACK

Код ошибки SQLITE_READONLY_ROLLBACK является расширенным кодом ошибки для SQLITE_READONLY. Код ошибки SQLITE_READONLY_ROLLBACK указывает, что нельзя открыть базу данных, потому что у нее есть горячий журнал, который нужно откат, но не может, потому что база данных только для чтения.

Во время разработки я часто прерываю текущее приложение для установки и запуска новой версии. Это приводит к тому, что текущее приложение будет принудительно остановлено системой. Если код Javascript в WebView находится в середине записи в базу данных через отдельное записываемое соединение, когда приложение запущено, тогда горячий журнал останется позади.

Когда запускается новая версия приложения, открывается соединение с базой данных только для чтения в собственном Java-коде. Когда это соединение вызывает журнал, он пытается отменить журнал. И поскольку это соединение только для чтения, оно терпит неудачу.

(Это соответствует тому, что авария наблюдается сразу после запуска после того, как я внес изменения).

Поэтому правильное исправление должно сделать соединение Java доступным для записи соединением. Это соединение никогда не пытается записать во время нормальной работы, но оно должно записываться при восстановлении из предыдущей прерванной записи через записываемое соединение WebView.