sqlite数据库链接池二

1、connectionpool.h

#ifndef CONNECTIONPOOL_H

#define CONNECTIONPOOL_H

#include "singleton.h"

#include <QSqlDatabase>

#include <QString>

#include <QStack>

#include <QSemaphore>

class ConnectionPoolObject;

class ConnectionPool

{

SINGLETON(ConnectionPool)

public:

void destory(); // 销毁连接池,关闭所有的数据库连接

QSqlDatabase openConnection(); // 获取数据库连接

void closeConnection(const QSqlDatabase& connection); // 释放数据库连接回连接池

private:

QSqlDatabase createConnection(const QString& connectionName); // 创建数据库连接

ConnectionPoolObject * object;

};

class ConnectionPoolObject

{

public:

ConnectionPoolObject();

~ConnectionPoolObject();

QStack<QString> usedConnectionNames; // 已使用的数据库连接名

QStack<QString> unusedConnectionNames; // 未使用的数据库连接名

// 数据库信息

QString databaseName;

QString databaseType;

bool testOnBorrow; // 取得连接的时候验证连接有效

QString testOnBorrowSql; // 测试访问数据库的 SQL

int maxWaitTime; // 获取连接最大等待时间

int maxConnectionCount; // 最大连接数

QSemaphore *semaphore;

static QMutex mutex;

static int lastKey; // 用来创建连接的名字,保证连接名字不会重复

};

#endif

2、connectionpool.cpp

#include "connectionpool.h"

#include <QtSql>

#include <QCoreApplication>

QMutex ConnectionPoolObject::mutex;

int ConnectionPoolObject::lastKey = 0;

ConnectionPoolObject::ConnectionPoolObject()

{

QString dbPath;

dbPath = QCoreApplication::applicationDirPath() +"/db/NELD_TSV790.db";

databaseName = dbPath;

databaseType = "QSQLITE";

testOnBorrow = true;

testOnBorrowSql = "SELECT 1";

maxWaitTime = 5000;

maxConnectionCount = 15;

semaphore = new QSemaphore(maxConnectionCount);

}

ConnectionPoolObject::~ConnectionPoolObject()

{

// 销毁连接池的时候删除所有的连接

foreach (QString connectionName, usedConnectionNames)

{

QSqlDatabase::removeDatabase(connectionName);

}

foreach (QString connectionName, unusedConnectionNames)

{

QSqlDatabase::removeDatabase(connectionName);

}

delete semaphore;

}

ConnectionPool::ConnectionPool() : object(new ConnectionPoolObject)

{

}

ConnectionPool::~ConnectionPool()

{

delete object;

}

QSqlDatabase ConnectionPool::openConnection()

{

Q_ASSERT(object != NULL);

if (object->semaphore->tryAcquire(1, object->maxWaitTime))

{

ConnectionPoolObject::mutex.lock();

QString connectionName;

if (object->unusedConnectionNames.size() > 0)

{

connectionName = object->unusedConnectionNames.pop();

}

else

{

connectionName = QString("C%1").arg(++ConnectionPoolObject::lastKey);

}

object->usedConnectionNames.push(connectionName);

ConnectionPoolObject::mutex.unlock();

QSqlDatabase db = createConnection(connectionName);

if (!db.isOpen())

{

ConnectionPoolObject::mutex.lock();

// object->usedConnectionNames.removeOne(connectionName);

QStack<QString> tempStack;

while (!object->usedConnectionNames.isEmpty())

{

QString top = object->usedConnectionNames.pop();

if (top != connectionName)

{

tempStack.push(top);

}

}

// 重新构建原始 QStack,不包含指定名称的元素

while (!tempStack.isEmpty())

{

object->usedConnectionNames.push(tempStack.pop());

}

ConnectionPoolObject::mutex.unlock();

object->semaphore->release();

}

return db;

}

else

{

return QSqlDatabase(); // 创建连接超时,返回一个无效连接

}

}

void ConnectionPool::closeConnection(const QSqlDatabase& connection)

{

Q_ASSERT(object != NULL);

QString connectionName = connection.connectionName();

if (object->usedConnectionNames.contains(connectionName))

{

QMutexLocker locker(&ConnectionPoolObject::mutex);

// object->usedConnectionNames.removeOne(connectionName);

QStack<QString> tempStack;

while (!object->usedConnectionNames.isEmpty()) {

QString top = object->usedConnectionNames.pop();

if (top != connectionName) {

tempStack.push(top);

}

}

// 重新构建原始 QStack,不包含指定名称的元素

while (!tempStack.isEmpty()) {

object->usedConnectionNames.push(tempStack.pop());

}

object->unusedConnectionNames.push(connectionName);

object->semaphore->release();

}

}

QSqlDatabase ConnectionPool::createConnection(const QString& connectionName)

{

Q_ASSERT(object != NULL);

if (QSqlDatabase::contains(connectionName))

{

QSqlDatabase existDb = QSqlDatabase::database(connectionName);

if (object->testOnBorrow)

{

QSqlQuery query(object->testOnBorrowSql, existDb);

if (query.lastError().type() != QSqlError::NoError && !existDb.open())

{

return QSqlDatabase();

}

}

return existDb;

}

QSqlDatabase db = QSqlDatabase::addDatabase(object->databaseType, connectionName);

db.setDatabaseName(object->databaseName);

if (!db.open())

{

return QSqlDatabase();

}

return db;

}

void ConnectionPool::destory()

{

if (object != NULL)

{

ConnectionPoolObject::mutex.lock();

delete object;

object = NULL;

ConnectionPoolObject::mutex.unlock();

}

}

3、Singleton.h

#ifndef SINGLETON_H

#define SINGLETON_H

#include <QMutex>

#include <QScopedPointer>

template <typename T>

class Singleton{

public:

Singleton(const Singleton& other);

Singleton<T>& operator=(const Singleton& other);

static T& getInstance();

private:

static QMutex mutex;

static QScopedPointer<T> instance;

};

template<typename T> QMutex Singleton<T>::mutex;

template<typename T> QScopedPointer<T> Singleton<T>::instance;

template<typename T>

T& Singleton<T>::getInstance()

{

if (instance.isNull())

{

mutex.lock();

if (instance.isNull())

{

instance.reset(new T());

}

mutex.unlock();

}

return *instance.data();

}

#define SINGLETON(Class) \

private: \

Class(); \

~Class(); \

Class(const Class& other); \

Class& operator=(const Class& other); \

friend class Singleton<Class>; \

friend struct QScopedPointerDeleter<Class>;

#endif

4、示例

SqliteDB g_db;

1、QSqlDatabase m_dataBase;

2、打开数据库

bool bRet = m_dataBase.isOpen()

m_dataBase = Singleton<ConnectionPool>::getInstance().openConnection();

3、检查是否存在表:

bool bRet = m_dataBase.tables().contains(m_TableName) ;

4、创建数据库表

QSqlQuery createTableQuery(m_dataBase);

createTableQuery.exec(m_TableName);

5、插入记录

QSqlQuery insertQuery(m_dataBase);

insertQuery.exec(insertSql)

6、更新记录

QSqlQuery updateQuery(m_dataBase);

updateQuery.exec(updateSql)

7、查询记录

QSqlQuery query(m_dataBase);

query.prepare(sql);

query.exec();

if (query.next())

{

experInfo.No = query.value("no").toString();

experInfo.Person = query.value("person").toString();

... ...

}

8、 关闭连接

Singleton<ConnectionPool>::getInstance().closeConnection(m_dataBase);

简单说明:

QStack 是 Qt 容器类库中提供的栈(LIFO,后进先出) 数据结构,继承自 QVector,因此它的底层实现是动态数组,兼具栈的操作特性和向量的高效访问能力。

核心特性

  1. 后进先出(LIFO):只能从栈顶插入 / 删除元素,不支持随机位置的插入操作。
  2. 继承自 QVector :可以直接使用 QVector 的方法(如 size()isEmpty()at() 等),同时扩展了栈专用接口。
  3. 值语义:元素会被拷贝存储,支持基本数据类型、Qt 数据类型及自定义类型(需实现拷贝构造函数)。

代码示例

cpp

运行

#include <QStack>

#include <QDebug>

int main() {

QStack<int> stack;

// 压入元素

stack.push(10);

stack.push(20);

stack.push(30);

// 访问栈顶元素

qDebug() << "Top element:" << stack.top(); // 输出 30

// 弹出栈顶元素

stack.pop();

qDebug() << "Top after pop:" << stack.top(); // 输出 20

// 遍历栈(注意:遍历顺序不是栈的弹出顺序)

for (int val : stack) {

qDebug() << val; // 输出 10, 20

}

return 0;

}

相关推荐
老华带你飞6 小时前
出行旅游安排|基于springboot出行旅游安排系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring·旅游
Logic1016 小时前
《数据库运维》 郭文明 实验4 数据库备份与恢复实验核心操作与思路解析
运维·数据库·sql·mysql·学习笔记·形考作业·国家开放大学
马克学长6 小时前
SSM物流信息管理系统35wzn(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·数字化管理·ssm 框架·物流信息管理
IndulgeCui6 小时前
KingbaseES 三权分立原则
数据库
JIngJaneIL6 小时前
基于Java饮食营养管理信息平台系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot
德彪稳坐倒骑驴7 小时前
SQL之前不懂,后来又学会的东西
数据库·sql
Maiko Star7 小时前
基于Redis ZSet实现多维度题目贡献度排行榜
数据库·redis·缓存
老华带你飞7 小时前
垃圾分类|基于springboot 垃圾分类系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring
CodeAmaz7 小时前
InnoDB的MVCC机制
java·数据库·mvcc