我收到如下错误:
Exception java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
原因是当我从表中获取数据时,巧合的是另一个服务开始运行以插入数据并且按照SQLite逻辑,插入命令关闭连接并且从表读取数据的服务得到连接池关闭错误
有人可以帮助我如何处理这个问题?我没有在所有设备上收到此错误。只有少数设备,有时也是如此。
我读了一些关于使用setWriteAheadLoggingEnabled(true)的问题。这是我可以在我的类构造函数中使用的吗?
我在DatabasWorking类中的插入方法,我从不同的类调用以插入数据。
public void insert(int deviceid, int productid) {
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("deviceid", deviceid);
contentValues.put("productid", productid);
sqLiteDatabase.insert(payment_table, null, contentValues);
sqLiteDatabase.close();
}
现在如何在此方法中使用单例。我需要在这里改变一下吗?
答案 0 :(得分:2)
我从multi-theads环境查询数据库时遇到了这个问题。由于getWritableDatabase()为同一个SQLiteOpenHelper返回相同的SQLiteDatabase对象,如果在一个线程中关闭它而另一个线程使用它,则会导致SQLiteConnectionPool关闭异常。我在这里分析了我的案例:java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed。
以下是您的代码建议:
从您的代码判断它可能存在于SQLiteOpenHelper对象中。您需要将其设为单例,因为一个SQLiteOpenHelper映射到一个db。没有必要在一个项目中为一个数据库保留太多SQLiteOpenHelper对象。你可以这样做:
// the PalmDB is your Helper name
class PalmDB extends SQLiteOpenHelper {
private static PalmDB sInstance = null;
public static PalmDB getInstance(final Context context){
if (sInstance == null){
synchronized (SQLiteOpenHelper.class) {
if (sInstance == null) {
// be sure to call getApplicationContext() to avoid memory leak
sInstance = new PalmDB(context.getApplicationContext());
}
}
}
return sInstance;
}
// ... next is the code for your insert method:
protected SQLiteDatabase getDatabase() {
OpenHelperManager.requireConnection();
return getWritableDatabase();
}
protected void closeDatabase() {
OpenHelperManager.releaseHelper(this);
}
/*
* Note that in this method, I didn't call getWriteDatabse() and SQLiteDatabase.close()
* to open and close db connection, instead I used two methods and added some options there.
*/
public synchronized void insert(int deviceid, int productid) {
SQLiteDatabase sqLiteDatabase = getDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("deviceid", deviceid);
contentValues.put("productid", productid);
sqLiteDatabase.insert(payment_table, null, contentValues);
closeDatabase();
}
}
接下来是SQLiteOpenHelper中使用的类:
public class OpenHelperManager {
@SuppressLint("StaticFieldLeak")
private static boolean isClosed = false;
private static int instanceCount = 0;
public static synchronized void releaseHelper(PalmDB helper) {
instanceCount--;
LogUtils.e(String.format("releasing helper %s, instance count = %s", helper, instanceCount));
if (instanceCount <= 0) {
if (helper != null) {
LogUtils.e(String.format("zero instances, closing helper %s", helper));
helper.close();
isClosed = true;
}
if (instanceCount < 0) {
LogUtils.e(String.format("too many calls to release helper, instance count = %s", instanceCount));
}
}
}
public static synchronized void requireConnection() {
isClosed = false;
instanceCount++;
}
public static boolean isClosed() {
return isClosed;
}
}
这里我使用静态和同步方法来锁定方法,并在每个方法中添加计算。当调用getWriteableDatabse()方法时,我将增加连接数,否则我会减少它。当连接数为0时,我关闭数据库连接池。我认为这可能是安全的,也关闭了连接。 (注意,关闭Helper类也将关闭SQLiteDatabse对象。您可以参考源代码。)
希望它有效!