试图写一个只读数据库…但我不是

我有一个只读的数据库连接。 有时,当用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(); } 

很less,我碰到这样的情况,在调用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模拟器和运行棒棒糖的设备上都发生了崩溃。


有一个单独的可写连接同时打开到同一个数据库,由WebView拥有。 数据库正在通过WebView中的Javascript代码进行更新,并使用此只读连接从本机Android / Java层进行读取。

我期望这可能是问题的根本原因,但我想详细了解为什么只读连接会干扰单独的可写连接。

我很清楚,一般的build议是使用一个单一的连接到数据库,但由于可写连接属于WebView ,所以我不能从Java代码中轻松访问它。

Solutions Collecting From Web of "试图写一个只读数据库…但我不是"

通过将其更改为可写的数据库连接来解决。 线索是在776错误代码的文档中 :

(776)SQLITE_READONLY_ROLLBACK

SQLITE_READONLY_ROLLBACK错误代码是SQLITE_READONLY的扩展错误代码。 SQLITE_READONLY_ROLLBACK错误代码表示数据库无法打开,因为它有一个需要回滚的热日志,但不能因为数据库是只读的。

在开发过程中,我经常中断正在运行的应用程序来安装并运行新版本。 这会导致当前正在运行的应用程序被系统强制停止。 如果WebView中的Javascript代码在应用程序被删除时正在通过单独的可写连接写入数据库,那么热日志将被留下。

当新版本的应用程序启动时,打开本地Java代码中的只读数据库连接。 当这个连接发现日志,它试图回滚日志。 而且因为它是一个只读连接,所以失败了。

(这适合于在我进行更改后立即在启动时观察到的崩溃。)

因此正确的解决方法是使Java连接成为可写连接。 此连接在正常操作期间从不尝试写入,但是在通过WebView的可写连接从先前中断的写入恢复时,它必须写入。