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