我正在使用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.app.Looper.loop(Looper.java:164)的os.Handler.dispatchMessage(Handler.java:106)位于android.app.ActivityThread.main(ActivityThread.java:6494)的java.lang.reflect.Method .invoke(本地方法)在com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run(RuntimeInit.java:438)在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)引起的:机器人.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)在玉米.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.ap的Android.app.Activity.performRestart(Activity.java:7088) p.Activity.performResume(Activity.java:7099)在android.app.ActivityThread.performResumeActivity(ActivityThread.java:3556)... 8更多
为什么在这种情况下连接是只读的?
可能您已经拥有可能尚未关闭的连接。
更具体地说,消息是从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
对象的实例。 **启用数据库连接池时,可以有多个到同一数据库的活动*连接。否则,每个数据库通常只有一个*连接。 *
*启用SQLite WAL功能时,多个阅读器和一个编写器*可以同时访问数据库。没有WAL,读者和作者*是互斥的。 *
* *所有权和并发保证
**连接对象不是线程安全的。根据需要获取它们以执行数据库操作,然后将其返回到池中。在任何*给定时间,连接由{@link SQLiteSession} *对象或{@link SQLiteConnectionPool}拥有和使用。这些类负责序列化操作以防止并发*使用连接。 *
*拥有单一所有者的保证允许在没有锁的情况下实现此类*并极大地简化了资源管理。 *
* *封装保证
**连接对象对象拥有与该连接关联的所有与SQLite相关的本机*对象。更重要的是,系统中没有其他对象能够获取*那些本机对象的句柄。因此,当连接关闭时,我们不必担心其他组件可能引用*其关联的SQLite状态 - 没有。 *
*封装是确保连接对象的*生命周期不会成为终结器和引用*队列的混乱。 *
* * @hide */