Qt 多线程操作数据库--数据库连接池

Qt 数据库连接池

参考博客

https://qtdebug.com/qtbook-db-connection-pool/

    * 数据库连接池特点:
    * 获取连接时不需要了解连接的名字,连接池内部维护连接的名字
    * 支持多线程,保证获取到的连接一定是没有被其他线程正在使用
    * 按需创建连接,可以创建多个连接,可以控制连接的数量
    * 连接被复用,不是每次都重新创建一个新的连接(连接的创建是一个很消耗资源的过程)
    * 连接断开了后会自动重连
    * 当无可用连接时,获取连接的线程会等待一定时间尝试继续获取,直到取到有效连接或者超时返回一个无效的连接
    * 关闭连接很简单

核心代码

QPair<bool, QSqlDatabase> ZLDBConnPool::openConnection(ZLDBConnPool::DbType emdbtype, const QString &connectionName)
{
    // 1. 创建连接的全名: 基于线程的地址和传入进来的 connectionName,因为同一个线程可能申请创建多个数据库连接
    // 2. 如果连接已经存在,复用它,而不是重新创建
    //    2.1 返回连接前访问数据库,如果连接断开,可以重新建立连接 (测试: 关闭数据库几分钟后再启动,再次访问数据库)
    // 3. 如果连接不存在,则创建连接
    // 4. 线程结束时,释放在此线程中创建的数据库连接

    // [1] 创建连接的全名: 基于线程的地址和传入进来的 connectionName,因为同一个线程可能申请创建多个数据库连接
    QString baseConnectionName = "conn_" + QString::number(quint64(QThread::currentThread()), 16);
    QString fullConnectionName = baseConnectionName +"_"+ connectionName;
//    qDebug() << fullConnectionName;
    if (QSqlDatabase::contains(fullConnectionName)) {
        // [2] 如果连接已经存在,复用它,而不是重新创建
        QSqlDatabase existingDb = QSqlDatabase::database(fullConnectionName);

        // [2.1] 返回连接前访问数据库,如果连接断开,可以重新建立连接 (测试: 关闭数据库几分钟后再启动,再次访问数据库)
        QSqlQuery query("SELECT 1", existingDb);

        if (query.lastError().type() != QSqlError::NoError && !existingDb.open()) {
            qDebug().noquote() << "Open datatabase error:" << existingDb.lastError().text();
            return {false,QSqlDatabase()};
        }

        return {true,existingDb};
    } else {
        // [3] 如果连接不存在,则创建连接
        if (qApp != nullptr) {
            // [4] 线程结束时,释放在此线程中创建的数据库连接
            QObject::connect(QThread::currentThread(), &QThread::finished, qApp, [fullConnectionName] {
                if (QSqlDatabase::contains(fullConnectionName)) {
                    QSqlDatabase::removeDatabase(fullConnectionName);
                    qDebug().noquote() << QString("Connection deleted: %1").arg(fullConnectionName);
                }
            });
        }

        return createConnection(emdbtype,fullConnectionName);
    }
}

多线程下测试:

可以看到每个线程都用了一次数据库连接,而且使用线程执行完了会自动销毁连接

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_a62610_sqlite, sn: 1

"1234"

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_9f3cc0_sqlite, sn: 2

"1234"

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_a438a0_sqlite, sn: 3

"1234"

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_a43680_sqlite, sn: 4

"1234"

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_a43800_sqlite, sn: 5

"1234"

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_a44060_sqlite, sn: 6

"1234"

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_a43bc0_sqlite, sn: 7

"1234"

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_a44700_sqlite, sn: 8

"1234"

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_a42ce0_sqlite, sn: 9

"1234"

支持数据库的驱动: ("QSQLITE", "QODBC", "QODBC3", "QPSQL", "QPSQL7")

Connection created: conn_69656b0_sqlite, sn: 10

"1234"

Connection deleted: conn_a62610_sqlite

Connection deleted: conn_9f3cc0_sqlite

Connection deleted: conn_a438a0_sqlite

Connection deleted: conn_a43680_sqlite

Connection deleted: conn_a43800_sqlite

Connection deleted: conn_a44060_sqlite

Connection deleted: conn_a43bc0_sqlite

Connection deleted: conn_a44700_sqlite

Connection deleted: conn_a42ce0_sqlite

Connection deleted: conn_69656b0_sqlite

完整源码下载地址:

https://download.csdn.net/download/ZLOZL/12821220

  • 0
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZLOZL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值