开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1103|回复: 23
收起左侧

[其它源码] [C++ Qt] SQLite 数据库连接池

[复制链接]
结帖率:100% (11/11)
发表于 2024-12-10 01:18:46 | 显示全部楼层 |阅读模式   河北省秦皇岛市
分享源码
界面截图: -
是否带模块: 纯源码
备注说明: -

特点如下:


  1. 单例模式

    • 使用单例模式确保全局只有一个连接池实例
    • 禁用了拷贝构造和赋值操作符
  2. 连接管理

    • 支持最大连接数限制 (m_maxConnections)
    • 支持初始连接数设置 (initialConnections)
    • 使用原子计数器 (m_connectionCounter) 跟踪连接总数
    • 维护可用连接队列 (m_availableConnections) 和使用中连接集合 (m_inUseConnections)
  3. 线程安全

    • 使用互斥锁保护共享资源
    • 使用条件变量实现等待/唤醒机制
    • 使用原子操作进行计数
  4. 智能指针管理

    • 使用 shared_ptr 自动管理连接的生命周期
    • DBConnection 析构时自动释放连接回连接池
  5. 连接复用机制

    • 优先使用可用连接
    • 当无可用连接且未达到最大连接数时创建新连接
    • 支持连接有效性检查和自动重连
  6. 错误处理

    • 连接创建失败时的回滚机制
    • 连接无效时的重新创建机制
    • 超时等待机制(5秒超时)
  7. 资源清理

    • 支持关闭所有连接
    • 正确处理事务回滚
    • 清理无效连接
  8. 数据库表管理

    • 支持表结构同步
    • 支持字段类型变更
    • 支持新增和删除字段

暂时没做其它功能, 有需求的同学自行扩展~

SqiiteUtils.zip

3.2 KB, 下载次数: 26, 下载积分: 精币 -2 枚

售价: 3 枚 精币  [记录]

评分

参与人数 2好评 +2 精币 +2 收起 理由
youxiaxy + 1 + 2 支持开源~!感谢分享
原子 + 1 YYDS~!

查看全部评分


本帖被以下淘专辑推荐:

结帖率:100% (11/11)

签到天数: 12 天

 楼主| 发表于 2024-12-10 22:24:21 | 显示全部楼层   河北省秦皇岛市
有点儿小修改, 改了一下同步表的逻辑, 现已支持复合主键:
bool SqliteUtils::SyncTable(const QString& tableName, const QMap<QString, FieldDefinition>& fieldDefinitions) {
    auto dbConnection = AcquireDBConnection();
    if (!dbConnection) {
        return false;
    }

    QSqlQuery sqlQuery(dbConnection->database());
    sqlQuery.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = :tableName");
    sqlQuery.bindValue(":tableName", tableName);

    if (!sqlQuery.exec()) {
        return false;
    }

    bool tableExists = sqlQuery.next();
    if (!tableExists) {
        QStringList fieldDefinitionList;
        QStringList primaryKeys;

        QString createTableSql = QString("CREATE TABLE %1 (").arg(tableName);
        for (auto it = fieldDefinitions.constBegin(); it != fieldDefinitions.constEnd(); ++it) {
            if (it.key() == "PRIMARY KEY") {
                if (!it.value().defaultValue.isEmpty()) {
                    primaryKeys.append(it.value().defaultValue);
                }
                continue;
            }

            QString fieldSql = QString("%1 %2").arg(it.key(), it.value().fieldType);

            if (it.value().notNull) {
                fieldSql += " NOT NULL";
            }

            if (!it.value().defaultValue.isEmpty()) {
                fieldSql += QString(" DEFAULT %1").arg(it.value().defaultValue);
            }

            if (it.value().isPrimaryKey) {
                fieldSql += " PRIMARY KEY";
            }

            fieldDefinitionList.append(fieldSql);
        }

        if (!primaryKeys.isEmpty()) {
            fieldDefinitionList.append(QString("PRIMARY KEY %1").arg(primaryKeys.join(", ")));
        }

        createTableSql += fieldDefinitionList.join(", ") + ")";
        return sqlQuery.exec(createTableSql);
    } else {
        sqlQuery.prepare(QString("PRAGMA table_info(%1)").arg(tableName));
        if (!sqlQuery.exec()) {
            return false;
        }

        bool requireUpdate = false;
        QMap<QString, QString> existingFieldTypes;
        while (sqlQuery.next()) {
            QString fieldName = sqlQuery.value(1).toString();
            QString fieldType = sqlQuery.value(2).toString();

            existingFieldTypes[fieldName] = fieldType;
            if (!fieldDefinitions.contains(fieldName)) {
                requireUpdate = true;
                continue;
            }

            if (fieldDefinitions[fieldName].fieldType.toUpper() != fieldType.toUpper()) {
                requireUpdate = true;
            }
        }

        for (auto it = fieldDefinitions.constBegin(); it != fieldDefinitions.constEnd(); ++it) {
            if (!existingFieldTypes.contains(it.key())) {
                requireUpdate = true;
                break;
            }
        }

        if (requireUpdate) {
            QString tempTableName = QString("%1_%2").arg(tableName).arg(QDateTime::currentMSecsSinceEpoch());

            QStringList selectFields;
            QStringList fieldDefinitionList;
            QStringList primaryKeys;
            QStringList actualFields;

            QString createTempTableSql = QString("CREATE TABLE %1 (").arg(tempTableName);
            for (auto it = fieldDefinitions.constBegin(); it != fieldDefinitions.constEnd(); ++it) {
                if (it.key() == "PRIMARY KEY") {
                    if (!it.value().defaultValue.isEmpty()) {
                        primaryKeys.append(it.value().defaultValue);
                    }
                    continue;
                }
                actualFields.append(it.key());

                QString fieldSql = QString("%1 %2").arg(it.key(), it.value().fieldType);

                if (it.value().notNull) {
                    fieldSql += " NOT NULL";
                }

                if (!it.value().defaultValue.isEmpty()) {
                    fieldSql += QString(" DEFAULT %1").arg(it.value().defaultValue);
                }

                if (it.value().isPrimaryKey) {
                    fieldSql += " PRIMARY KEY";
                }

                fieldDefinitionList.append(fieldSql);

                if (existingFieldTypes.contains(it.key())) {
                    if (it.value().fieldType.toUpper() == "INTEGER") {
                        selectFields.append(QString("CAST(ROUND(CASE WHEN %1 GLOB '*[0-9]*' THEN %1 ELSE 0 END) AS INTEGER) AS %1").arg(it.key()));
                    } else if (it.value().fieldType.toUpper() == "REAL") {
                        selectFields.append(QString("CAST(CASE WHEN %1 GLOB '*[0-9]*' THEN %1 ELSE 0 END AS REAL) AS %1").arg(it.key()));
                    } else if (it.value().fieldType.toUpper() == "TEXT") {
                        selectFields.append(QString("CAST(%1 AS TEXT) AS %1").arg(it.key()));
                    } else {
                        selectFields.append(it.key());
                    }
                } else {
                    if (!it.value().defaultValue.isEmpty()) {
                        selectFields.append(QString("%1 AS %2").arg(it.value().defaultValue, it.key()));
                    } else {
                        selectFields.append("NULL AS " + it.key());
                    }
                }
            }

            if (!primaryKeys.isEmpty()) {
                fieldDefinitionList.append(QString("PRIMARY KEY %1").arg(primaryKeys.join(", ")));
            }

            createTempTableSql += fieldDefinitionList.join(", ") + ")";
            if (!sqlQuery.exec(createTempTableSql)) {
                return false;
            }

            QString copyDataSql = QString("INSERT INTO %1 (%2) SELECT %3 FROM %4").arg(tempTableName, actualFields.join(", "), selectFields.join(", "), tableName);
            if (!sqlQuery.exec(copyDataSql)) {
                return false;
            }

            QString dropTableSql = QString("DROP TABLE IF EXISTS %1").arg(tableName);
            if (!sqlQuery.exec(dropTableSql)) {
                return false;
            }

            QString renameTableSql = QString("ALTER TABLE %1 RENAME TO %2").arg(tempTableName, tableName);
            return sqlQuery.exec(renameTableSql);
        } else {
            return true;
        }
    }
}
回复 支持 反对

使用道具 举报

签到天数: 3 天

发表于 2025-2-11 10:48:33 | 显示全部楼层   江西省南昌市
回复 支持 反对

使用道具 举报

结帖率:100% (1/1)
发表于 2024-12-15 08:31:46 | 显示全部楼层   山东省济南市
学习数据库连接正需要
回复 支持 反对

使用道具 举报

签到天数: 4 天

发表于 2024-12-12 22:31:08 | 显示全部楼层   广西壮族自治区北海市
感谢分享,很给力!~
回复 支持 反对

使用道具 举报

签到天数: 20 天

发表于 2024-12-11 21:53:11 | 显示全部楼层   江苏省常州市
感谢分享!
回复 支持 反对

使用道具 举报

签到天数: 2 天

发表于 2024-12-11 14:48:48 | 显示全部楼层   湖南省湘西土家族苗族自治州
nbifdsffdgfdgdfgfdgdfgdf
回复 支持 反对

使用道具 举报

结帖率:0% (0/1)

签到天数: 2 天

发表于 2024-12-11 14:46:54 | 显示全部楼层   北京市北京市
666666666666666666666666666666666666666666
回复 支持 反对

使用道具 举报

结帖率:100% (4/4)

签到天数: 25 天

发表于 2024-12-11 12:28:05 | 显示全部楼层   山东省淄博市
感谢分享
回复 支持 反对

使用道具 举报

签到天数: 4 天

发表于 2024-12-10 21:05:53 | 显示全部楼层   湖北省黄冈市
感谢分享学习。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表