Android: cannot complete this operation because connection pool is closed

I read through stackoverflow about this question, and I still haven't found a solution. I noticed that sometimes the application changes this error:

java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed. at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962) at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599) at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348) at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894) ... 

I have a DatabaseHelper.java file using this approach to get an instance of it:

 public static DatabaseHelper getInstance(Context context) { if (mInstance == null) { mInstance = new DatabaseHelper(context.getApplicationContext()); } return mInstance; } 

Then I have methods like this (that it crashed in the line cursor.moveToFirst () with this error). It almost never crashes, but sometimes it happens.

 public Profile getProfile(long id) { SQLiteDatabase db = this.getReadableDatabase(); String selectQuery = "SELECT * FROM " + TABLE_PROFILES + " WHERE " + KEY_PROFILES_ID + " = " + id; Cursor cursor = db.rawQuery(selectQuery, null); // looping through all rows and adding to list Profile profile = new Profile(); if (cursor.moveToFirst()) { doWhatEver(); } cursor.close(); db.close(); return profile; } 

So that he uses all the methods that I use:

 SQLiteDatabase db = this.getReadableDatabase(); (or Writable) 

And then I close the cursor and db. In this case, the error hit the line:

 cursor.moveToFirst(); 

I don’t understand why the error says that db is closing if I call this.getReadableDatabase () earlier. Please Support! Thank:)

+42
java android database sqlite singleton
Apr 25 '14 at 12:44
source share
6 answers

Delete

 db.close(); 

If you try another operation after closing the database, it will give you this exception.

The documentation says:

Releases an object reference, closes an object ...

Also, check out the Android Sq Lite Closed Exception for a comment from the Android Framework developer that says you don't need to close the database connection.

+61
Apr 25 '14 at 13:00
source share

I am currently having the same issue. By choosing db.close (), solve the problem for me, I think the problem is caused by multi-threading. Here are my studies.

SQLiteOpenHelper contains a reference to SQLiteDatabase, when getReadableDatabase () or getWritableDatabase () is called, it will return the link if SQLiteDatabase is closed or null, a new SQLiteDatabase object will be created. Note that inside the get method, codes are protected in a synchronized block.

SQLiteDatabase is a subclass of SQLiteClosable. SQLiteClosable implements a reference counting scheme.

  • At the first creation, the counter is 1.

  • When database working methods (for example, insert, query) are started, this will increase the counter and decrease the counter when the methods run out. But cursor operations are NOT protected by reference counting.

  • If the counter decreases to 0, the connection pool will be closed, and the object of the SQLiteConnectionPool object will be null, and now SQLiteDatabase will be closed ;

  • SQLiteDatabase.close () will decrease the score by 1;

So, if you have a single-threaded schema, closing SQLiteDatabase will be fine, because SQLiteOpenHelper simply re-creates it.

If you are doing multithreading then you will have problems. Let's say stream A and stream B both call getReadableDatabase (), and SQLiteOpenHelper returns the SQLiteDatabase that it stores, and then the stream first terminated and called SQLiteDatabase.close (), now the stream of SQLiteDatabase B objects is closed , so any subsequent operation calls db or cursor method calls will throw an exception.

+13
Jun 01 '16 at 8:08
source share

I have the same problem, failed to fix it. I found a possible hint: I have a synchronization thread that works all the time:

  Item ii = dbHelper.popPendingUpload(); if (ii != null) upload(ii); 

And inside DBHelper

 public Item popPendingUpload() { SQLiteDatabase db = getReadableDatabase(); Cursor res = db .rawQuery("SELECT * FROM items WHERE state = 0 LIMIT 1", new String[] {}); boolean hasNext = res.moveToFirst(); Item ii = null; if (hasNext) { ii = //load item } db.close(); return ii; } 

The error also appears in a call to the moveToFirst () method. Since the thread issues elements in an infinite loop, the first time it works fine, the second time an error occurs. The interesting part is that if I put a breakpoint and go through the code, the error will no longer be displayed. I am testing on a real device using Android 4.1.

I know this is not an answer, but it can help. I will continue testing.

+3
Sep 23 '14 at 23:16
source share
 //close database after cursor is closed like: if(cursor.getCount() != 0){ while(cursor.moveToNext()){ //do operation } } cursor.close(); database.close(); 
+2
Jul 29 '16 at 5:20
source share

You may close the database before accessing the database from your application.

You need to change getProfile () to

 public Profile getProfile(long id) { SQLiteDatabase db = this.getReadableDatabase(); try { String selectQuery = "SELECT * FROM " + TABLE_PROFILES + " WHERE " + KEY_PROFILES_ID + " = " + id; Cursor cursor = db.rawQuery(selectQuery, null); // looping through all rows and adding to list Profile profile = new Profile(); if (cursor.moveToFirst()) { doWhatEver(); } cursor.close(); finally { db.close(); } return profile; } 
0
Mar 23 '16 at 5:30
source share

I have an error like yours, here is my code:

  try { String sql = "SELECT * FROM "+DB_TABLEDOWNLOAD; Cursor cursor = db.rawQuery(sql, null); //空双引号为原表没有的字段String temp = ""; int existIconPath = cursor.getColumnIndex("iconPath"); int existAudioID = cursor.getColumnIndex("audioID"); if (existIconPath == -1 && existAudioID == -1){ temp = "url, downed,total,path,name, audioTitle, audioFileID,\"\",\"\""; }else if (existIconPath == -1 && existAudioID != -1){//iconPath不存在temp = "url, downed,total,path,name, audioTitle, audioFileID,\"\",audioID"; }else if (existIconPath != -1 && existAudioID == -1){//audioID不存在temp = "url, downed,total,path,name, audioTitle, audioFileID,iconPath,\"\""; }else { return; } db.beginTransaction(); String tempTableName = "_temp_"+DB_TABLEDOWNLOAD; String sqlCreateTemp = " ALTER TABLE "+DB_TABLEDOWNLOAD+" RENAME TO "+tempTableName+";"; db.execSQL(sqlCreateTemp); final String TB_TESTPAPERINFO_CREATE = "Create TABLE IF NOT EXISTS " + DB_TABLEDOWNLOAD + "(url TEXT, downed TEXT,total TEXT,path TEXT,name TEXT, audioTitle TEXT, audioFileID TEXT,iconPath TEXT, audioID TEXT);"; db.execSQL(TB_TESTPAPERINFO_CREATE); String sqlBackupData = "INSERT INTO "+DB_TABLEDOWNLOAD+" SELECT "+temp+" FROM "+tempTableName+";"; db.execSQL(sqlBackupData); String sqlDrop = "DROP TABLE IF EXISTS '"+tempTableName+"';"; db.execSQL(sqlDrop); db.setTransactionSuccessful(); } catch (Exception e) { e.printStackTrace(); }finally{ db.endTransaction(); } 
I use return before db.beginTransaction (), my code returns before beginTransaction, but ultimately endTransaction. if you do not start Transaction and endTransaction, an exception will be thrown.

so check your code about db.beginTransaction and endTransaction.

0
Jan 16 '17 at 7:23
source share



All Articles