Exception java.lang.IllegalStateException: Cannot perform this operation because the connection pool

当我在多线程环境当中使用数据库的时候遇到了这个问题。这是我之间在 StackOverflow 上面的回答的答案:Avoiding Connection Pool Closed in SQLite

因为同一个 SQLiteOpenHelper 的 getWritableDatabase() 返回同一个 SQLiteDatabase 对象,所以当在多线程环境当中使用 SQLiteDatabase 的时候就,如果一个线程关闭了 SQLiteDatabase 而另一个线程只在使用它就会出现 SQLiteConnectionPool close exception。我在之前的回答也分析过这个问题:java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed

所以,当我们在 Android 中使用数据库的时候,可以按照下面的方式设计:

// 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();
    }
}

这里我们使用单例的 PalmDB 来操作数据库。并定义了一个工具类 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;
    }
}

当创建和断开数据库连接的时候,我们都会在 SQLiteOpenHelper 中进行记录。并且当所有的连接都关闭的时候,我们就关闭 PalmDB。

以上是一种解决方案,在我的开源项目中,我们自己设计了一套数据库访问的逻辑,你可以通过 Github 来参考它的代码:马克笔记

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值