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;

}

相关推荐
小陈工2 小时前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
科技小花6 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸6 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain6 小时前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希7 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神7 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员7 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java7 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿7 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴7 小时前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存