我正在使用sqlite db并使用Alex LockWood Correctly Managing Your SQLite Database
的一些代码效果很好,但有时我收到错误"java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed."
这是完整的错误:
02-20 16:37:21.385: W/dalvikvm(25730): threadid=13: thread exiting with uncaught exception (group=0x41c122a0)
02-20 16:37:21.390: E/AndroidRuntime(25730): FATAL EXCEPTION: Timer-0
02-20 16:37:21.390: E/AndroidRuntime(25730): java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
02-20 16:37:21.390: E/AndroidRuntime(25730): at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:963)
02-20 16:37:21.390: E/AndroidRuntime(25730): at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:678)
02-20 16:37:21.390: E/AndroidRuntime(25730): at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:349)
02-20 16:37:21.390: E/AndroidRuntime(25730): at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
02-20 16:37:21.390: E/AndroidRuntime(25730): at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834)
02-20 16:37:21.390: E/AndroidRuntime(25730): at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
02-20 16:37:21.390: E/AndroidRuntime(25730): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143)
02-20 16:37:21.390: E/AndroidRuntime(25730): at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
02-20 16:37:21.390: E/AndroidRuntime(25730): at com.uit.pokemon.DatabaseHandler.getStadiumStatusById(DatabaseHandler.java:533)
02-20 16:37:21.390: E/AndroidRuntime(25730): at playground.RoomActivity.checkTable(RoomActivity.java:276)
02-20 16:37:21.390: E/AndroidRuntime(25730): at playground.RoomActivity$6.run(RoomActivity.java:321)
02-20 16:37:21.390: E/AndroidRuntime(25730): at java.util.Timer$TimerImpl.run(Timer.java:284)
02-20 16:37:21.460: I/timertask cancel(25730): canceled
以下是导致错误的代码:
public int getStadiumStatusById(int dataStadiumId){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cur = db.rawQuery("SELECT " + keyStadiumId + " as _id, "
+ keyRoomName + ", " + keyP1Name + ", " + keyP1PokemonName
+ ", " + keyP1PokemonLevel + ", " + keyP1PokemonHp + ", "
+ keyP2Name + ", " + keyP2PokemonName + ", "
+ keyP2PokemonLevel + ", " + keyP2PokemonHp + ", "
+ keyTimeCreate + ", " + keyStadiumStatus + " from "
+ tbl_stadium + " WHERE " + keyStadiumId + " = " + "'"
+ dataStadiumId + "'", new String[] {});
int stadiumStatus = 0;
if(cur.getCount()>0)
{
cur.moveToFirst();
stadiumStatus = cur.getInt(11);
}
db.close();
cur.close();
return stadiumStatus;
}
我尝试谷歌搜索了很多个小时但没有结果。请帮我修理一下。任何帮助将不胜感激。谢谢!
答案 0 :(得分:0)
我也在处理这个问题。我对原因有所了解,并希望听到专家对此的看法。我做了很多假设,得出了一些没有证据支持的结论......
我认为“返回stadiumStatus”行会抛出异常。上面几行,您将此变量分配给Cursor的成员。我相信你实际上是将sportsStatus这个名称指定为一个只存在于游标中的int变量。另一种可能性(逻辑的巨大飞跃)是Cursor.getInt()返回的项实际上是一个指向开放数据库中的项(一个方法?)的指针(由于它是打开的,它驻留在内存中)。无论哪种方式,当你关闭Cursor和/或数据库然后尝试返回stadiumStatus时,int指向 Cursor中的地址或传递 Cursor,尝试跟随它,并且死角结束于关闭的Cursor或关闭的数据库(其中一个是您正在绘制的“数据池”。)
如果我是对的,我认为最好的解决办法是替换:
“stadiumStatus = cur.getInt(11);”
使用:
“stadiumStatus = new Integer(cur.getInt(11));”
从而在内存中创建一个新的Integer,vm可以简单地转换为int,并且仅依赖于其传统的可访问性范围。
这个答案有意义吗?我确信提问者早已解决了这个问题,但我希望能够说我回答了一个关于Stack Overflow的问题(或者告诉我为什么我错了,并且更好地理解游标和数据库)。
编辑:这些答案意味着我可能是对的:
Android error: Cannot perform this operation because the connection pool has been closed
Will cursor be still alive after database is closed?
在第二个答案中,具有巨大声誉的用户DeeV将游标称为“持久连接”,这意味着它不是来自数据库的返回值的简单集合。
答案 1 :(得分:0)
在您使用的代码中:
db.close();
cur.close();
最佳做法是首先关闭游标然后关闭数据库,因为一旦调用db.close()
,它将使数据库冻结关闭并且其相应的游标无效。尝试这种改变它会起作用。
将其替换为:
cur.close();
db.close();
答案 2 :(得分:0)
我发现在多线程中使用数据库时也会发生此异常。因此,最好在synchronized
和db = helper.getXXXDatabase()
db.close()
答案 3 :(得分:0)
由SQLiteOpenHelper
类打开的数据库在类的生命周期内保持打开状态。
因此无需打开和关闭数据库。事实上,如果它在多个线程上使用,那就错了。
我的应用程序已经有一段时间没有数据库错误了,我有一个帮助类。这需要是一个单例,因此SqliteDatabase的不同实例不会同时尝试修改该文件。
此外我曾经发现的一些崩溃表明游标和查询都可以调用sqlite查询,因此允许对数据库进行并发读写访问是没有意义的。
出于这个原因,我向助手添加了一个读写器锁,并使用这种模式...
public static class MyDbHelper extends SQLiteOpenHelper {
private MyDbHelper (Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public static MyDbHelper mInstance;
private static Object mObj = new Object();
public static MyDbHelper getInstance( Context context ){
synchronized (mObj ){
if( mInstance == null ){
mInstance = new MyDbHelper ( context );
}
}
return mInstance;
}
private ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
public Lock readLock() {
return mLock.readLock();
}
public Lock writeLock() {
return mLock.writeLock();
}
使用类是这样的......
MyStorageContract.MyDbHelper helper = MyStorageContract.MyDbHelper.getInstance(this);
SQLiteDatabase db = helper.getReadableDatabase();
helper.readLock().lock();
try {
String[] columns = {
MyStorageContract.Libraries.COLUMN_NAME_LIBRARY_ID,
MyStorageContract.Libraries.COLUMN_NAME_LIBRARY_DIR,
MyStorageContract.Libraries.COLUMN_NAME_LIBRARY_SOMETHING,
};
String result = null;
Cursor c = db.query(MyStorageContract.Libraries.TABLE_NAME, columns, null, null, null, null, null, "1");
int idxDir = c.getColumnIndex(MyStorageContract.Libraries.COLUMN_NAME_LIBRARY_DIR);
int idxRoot = c.getColumnIndex(MyStorageContract.Libraries.COLUMN_NAME_LIBRARY_SOMETHING);
int idxId = c.getColumnIndex(MyStorageContract.Libraries.COLUMN_NAME_LIBRARY_ID);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
result = c.getString(idxDir);
}
c.close();
return result;
}
finally {
helper.readLock().unlock();
}
答案 4 :(得分:0)
我遇到了这个问题并在此解决了java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed。在我的例子中,我分析了android的数据库框架。 mime的真正原因是我在许多用于保存和查询数据的商店对象中使用SQLiteDatabase。由于SQLiteOpenHelper是单例,因此SQLiteDatabase也是单例。即使我在一个商店中添加了sychronized,它仍然在另一个商店中解锁。因此,如果我忘记在一个地方删除SQLiteDatabase.close(),它将导致SQLiteConnectionPool关闭。此外,我还添加了一些方法来释放SQLite连接。希望它有所帮助。
答案 5 :(得分:-6)
致电
db.open()
这一行之后:
SQLiteDatabase db = this.getReadableDatabase();
但是,我个人不知道this.getReadableDatabase()
究竟是怎么做的,但我只想制作自己的数据库适配器。有关详细信息,请参阅此链接:http://www.vogella.com/articles/AndroidSQLite/article.html