为什么此连接是只读的?

时间:2017-12-21 10:53:49

标签: java android sqlite android-sqlite greendao

我使用greenDao作为ORM,现在我正试图让应用程序多线程,因为性能问题。 以下是我打开连接的方式:

class appClass extends Application{
@Override    
public void onCreate(){
     DaoMaster.OpenHelper helper = new DaoMaster.OpenHelper(this, "my-db", null);
     final SQLiteDatabase db = helper.getWritableDatabase();
     final DaoMaster daoMaster = new DaoMaster(db);
     daoSession = daoMaster.newSession();
}

有时应用程序会崩溃

  

.SQLiteException:无法执行此语句,因为它可能   修改数据库,但连接是只读的。

这里是Stacktrace:

  

java.lang.RuntimeException:无法恢复活动   {} com.my.app.android/com.my.app.android.ui.ListActivity:   android.database.sqlite.SQLiteException:无法执行此语句   因为它可能会修改数据库,但连接是只读的。       在android.app.ActivityThread.performResumeActivity(ActivityThread.java:3581)       在android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621)       在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1638)       在android.os.Handler.dispatchMessage(Handler.java:106)       在android.os.Looper.loop(Looper.java:164)       在android.app.ActivityThread.main(ActivityThread.java:6494)       at java.lang.reflect.Method.invoke(Native Method)       在com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run(RuntimeInit.java:438)       在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)引起:android.database.sqlite.SQLiteException:无法执行   此语句因为它可能会修改数据库但连接   是只读的。       在android.database.sqlite.SQLiteConnection.throwIfStatementForbidden(SQLiteConnection.java:1026)       在android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:730)       在android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)       在android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)       在android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1754)       在android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1682)       在com.my.app.android.orm.generated.ObjektDao.deleteOPTempTable(ObjektDao.java:479)       在com.my.app.android.orm.generated.ObjektDao.reBuildOPTempTable(ObjektDao.java:544)       在com.my.app.android.TempTablesUtils.checkTempTables(TempTablesUtils.java:132)       在com.my.app.android.ui.ListActivity.onRestart(ListActivity.java:94)       在android.app.Instrumentation.callActivityOnRestart(Instrumentation.java:1344)       在android.app.Activity.performRestart(Activity.java:7088)       在android.app.Activity.performResume(Activity.java:7099)       在android.app.ActivityThread.performResumeActivity(ActivityThread.java:3556)       ......还有8个

为什么在这种情况下连接是只读的?

1 个答案:

答案 0 :(得分:0)

可能你已经拥有了可能尚未关闭的联系。

更具体地说,该消息是从 SQLiteConnection.java 行709-714内发出的: -

private void throwIfStatementForbidden(PreparedStatement statement) {
    if (mOnlyAllowReadOnlyOperations && !statement.mReadOnly) {
        throw new SQLiteException("Cannot execute this statement because it "
                + "might modify the database but the connection is read-only.");
    }
}

该文件中的评论包括: -

  

/ ** *表示SQLite数据库连接。 *每个连接   包装本机sqlite3对象的实例。 *

*   启用数据库连接池时,可能有多个   active *连接到同一个数据库。否则有   通常每个数据库只有一个*连接。 *

*当   SQLite WAL功能已启用,多个阅读器和一个编写器*可以   同时访问数据库。没有WAL,读者和作家*   相互排斥。 *

* *

所有权和并发性   保证

*

*连接对象不是线程安全的。   根据需要获取它们以执行数据库操作   然后回到游泳池。在任何*给定时间,连接是   由@@link SQLiteSession} *对象拥有和使用   {@link SQLiteConnectionPool}。这些课程负责   序列化操作以防止并发*使用a   连接。 *

*拥有单一所有者的保证   允许这个类在没有锁的情况下实现*   简化资源管理。 *

* *

封装   保证

*

*连接对象对象拥有所有   与SQLite相关的本机*对象   连接。更重要的是,系统中没有其他对象   能够获得*那些本机对象的句柄。   因此,当连接关闭时,我们不需要   担心其他组件可能引用*它的内容   关联的SQLite状态 - 没有。 *

*封装   是确保连接对象的生命周期没有的原因   成为一个折磨混乱的终结者和参考*队列。 *

  * * @hide * /