我发布了我的应用程序的更新,并从用户那里收到了大量错误,但我无法重新创建它或查明问题所在。
我得到两个错误: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase
java.lang.IllegalStateException: database not open
错误发生在以下代码中的某处:
public DBUserC getUser(int _id){
synchronized (DBAdapter.LOCK){
M.openDB(context);
Cursor cursor = M.database.query(DBUserHelper.TABLE_USERS,
VUser.allColumns, DBUserHelper.COLUMN_ID + " = '"+_id+"'", null, null, null, null);
DBUserC user;
if (cursor.moveToFirst()){
user = cursorToInfo(cursor);
} else{
user = newUser();
}
cursor.close();
M.closeDB();
return user;
}
}
在此版本中,有一个数据库升级,其中我通过db.execSql
执行三个查询。它不在单独的线程中。
每次调用数据库时(onUpgrade
除外),我都会同步,然后打开它,运行我的代码,然后关闭它。在这次升级之前,我没有遇到任何问题,找不到问题。
任何帮助将不胜感激。
编辑:要打开我的数据库,我这样做:
if (helper==null)
helper = new DBAdapter(context);
if (database==null){
database = helper.getWritableDatabase();
} else if (!database.isOpen())
database = helper.getWritableDatabase();
并关闭:
helper.close();
helper = null;
database = null;
获取信息的示例方法:
public DBUserC getUser(int _id){
synchronized (DBAdapter.LOCK){
openDB(context);//this is the open code above
Cursor cursor = M.database.query(DBUserHelper.TABLE_USERS,
VUser.allColumns, DBUserHelper.COLUMN_ID + " = '"+_id+"'", null, null, null, null);
DBUserC user;
if (cursor.moveToFirst()){
user = cursorToInfo(cursor);//does not contain DB operations
} else{
user = newUser(); ////does not contain Database operations
}
cursor.close();
closeDB();//This is the close code above
return user;
}
}
AHost.onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
M.initializeDB(context); //synchronized call to the openDB code I posted above
M.openDataDB(context); //opens a different database by a different file name. This DB is not an issue
//irrelevant ui setup
int _id = pref.getInt(P.eLastUser, VUser.ID_NEW);//row id of user
M.requeryUser();//synchronized, access database
M.switchUser(_id);//synchronized, access database
}
我在我的一个应用程序中遇到了同样的问题,我如何解决这个问题是通过删除 cursor.close()。希望它能有所帮助:)
我无法重现问题,因为在测试中,我正在从数据库版本 3 升级到版本 4。我的许多用户正在从版本 2 升级到版本 4。从 2 升级到 3 的一些代码是基于方法的。我最终为版本 4 更改了其中一些方法,这破坏了版本 3 的升级。然后,我从 cursorToObject() 方法中捕获了一个异常,这导致跳过 database.close,然后我得到了 sqlite 异常
显然,我们需要看到升级方法似乎是您问题的根本原因。 我使用亚当斯升级方法,我为博客命名它,我发现它是oun。
注意:每次升级都是在升级到 <= newVersion 循环中完成的。 也许有一天我会在这个循环上放一个进度条。
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
int upgradeTo = oldVersion + 1;
while (upgradeTo <= newVersion) {
switch (upgradeTo) {
// update old resrawid's to constants
// this was caused when I saved R values in the database
// and then later realized they would change.
// the old resrawid is changed to a constant.
case 42:
ContentValues values;
@SuppressWarnings("unused")
// used for debugging so I can see the value of the update.
int res;
int rs;
rs = 2130968576;
values = new ContentValues();
values.put(
KEY_RESRAWID,
com.gosylvester.bestrides.ImageTextListViewActivity.SAMPLE_DRAGON);
res = db.update(TABLE_RIDES, values, KEY_RESRAWID + " = ?",
new String[] { String.valueOf(rs) });
rs = 2130968577;
values = new ContentValues();
values.put(
KEY_RESRAWID,
com.gosylvester.bestrides.ImageTextListViewActivity.SAMPLE_M119);
res = db.update(TABLE_RIDES, values, KEY_RESRAWID + " = ?",
new String[] { String.valueOf(rs) });
rs = 2130968578;
values = new ContentValues();
values.put(
KEY_RESRAWID,
com.gosylvester.bestrides.ImageTextListViewActivity.SAMPLE_MEDINA);
res = db.update(TABLE_RIDES, values, KEY_RESRAWID + " = ?",
new String[] { String.valueOf(rs) });
break;
case 43:
// new column added for last_viewed.
db.execSQL(VERSION_43_ALTER);
break;
case 44:
// new index on KEY_DATE_UPDATE DESC
db.execSQL(VERSION_44_CREATE_INDEX);
}
upgradeTo++;
}
}
祝你好运丹尼117