基于Qt封装数据库基本增删改查操作,支持多线程,并实现SQLite数据库单例访问

抽出来的,直接用就行

  • 头文件
  • CPP文件
  • 使用示例

头文件

#ifndef DATABASECOMMON_H
#define DATABASECOMMON_H/** 单例封装SQLite通用操作,支持多线程调用;可扩展兼容其他数据库,照着SysRunDatabase写,并且重载openDatabase即可* 使用步骤:1、主线程addDatabase,调用setDatabase*         2、setDatabaseName*         3、按需setUserName、setPassword*         4、openDatabase*         5、查询使用execSelect,建表使用execNormalSQL,插入、修改、删除等操作使用execTransaction*         6、closeDatabase(程序生命周期内不需要显式调用,这里仅预留)
*/#include <QObject>
#include <QSqlDatabase>
#include <QSqlQueryModel>
#include <QMutex>
/** 类名:DatabaseCommon* 功能:数据库基础操作抽象类,由子类实现openDatabase操作* 使用方法:子类化DatabaseCommon,并实现openDatabase函数
*/
class DatabaseCommon: public QObject
{Q_OBJECT
public:void setDatabase(QSqlDatabase db);void setDatabaseName(QString dbName);void setUserName(QString userName);void setPassword(QString password);virtual bool openDatabase() = 0;//不同数据库的打开方式不同void closeDatabase();bool execNormalSQL(const QString &sqlString);bool execSelect(const QString &sqlString, QSqlQueryModel &model);bool execTransaction(const QString &sqlString);bool execTransaction(const QStringList &sqlStrings);
private:DatabaseCommon(const DatabaseCommon&) = delete;DatabaseCommon& operator=(const DatabaseCommon&) = delete;
protected:explicit DatabaseCommon(QObject *parent = nullptr){}virtual ~DatabaseCommon();QSqlDatabase mDatabase;QString mDatabaseName = "";QString mUserName = "";QString mPassword = "";QMutex mMutex;//保证多线程访问安全
};
/** 类名:SysRunDatabase* 功能:应用于SysRun.db数据库,使用全局单例进行访问
*/
class SysRunDatabase : public DatabaseCommon
{Q_OBJECT
public:static SysRunDatabase& Instance(){static SysRunDatabase mInstance;return mInstance;}bool openDatabase() override;
protected:explicit SysRunDatabase(QObject *parent = nullptr){}~SysRunDatabase() override {}
private:SysRunDatabase(const SysRunDatabase&) = delete;SysRunDatabase& operator=(const SysRunDatabase&) = delete;
};#endif // DATABASECOMMON_H

CPP文件

#include "databasecommon.h"
#include <QDebug>
#include <QSqlQuery>
#include <QFile>
#include <QException>
#include <QSqlError>
#include <QMutexLocker>DatabaseCommon::~DatabaseCommon()
{closeDatabase();
}
/** 函数名称:setDatabase* 功能说明:设置数据库对象* 输入参数:数据库对象* 输出参数:无* 其他说明:无*/
void DatabaseCommon::setDatabase(QSqlDatabase db)
{QMutexLocker locker(&mMutex);this->mDatabase = db;
}
/** 函数名称:setDatabaseName* 功能说明:设置数据库名称(对于SQLite,就是db文件路径)* 输入参数:数据库名称* 输出参数:无* 其他说明:无*/
void DatabaseCommon::setDatabaseName(QString dbName)
{QMutexLocker locker(&mMutex);this->mDatabaseName = dbName;
}
/** 函数名称:setUserName* 功能说明:设置数据库用户名* 输入参数:用户名* 输出参数:无* 其他说明:无*/
void DatabaseCommon::setUserName(QString userName)
{QMutexLocker locker(&mMutex);this->mUserName = userName;
}
/** 函数名称:setPassword* 功能说明:设置数据库用户密码* 输入参数:用户密码* 输出参数:无* 其他说明:无*/
void DatabaseCommon::setPassword(QString password)
{QMutexLocker locker(&mMutex);this->mPassword = password;
}
/** 函数名称:openDatabase* 功能说明:打开数据库连接* 输入参数:无* 输出参数:无* 其他说明:无*/
bool SysRunDatabase::openDatabase()
{QMutexLocker locker(&mMutex);if(!QFile::exists(mDatabaseName)){qCritical() << "not exist " << mDatabaseName;return false;}mDatabase.setDatabaseName(mDatabaseName);mDatabase.setUserName(mUserName);mDatabase.setPassword(mPassword);if(!mDatabase.open()){qCritical() << "open failed."<< mDatabase.lastError().text();return false;}return true;
}
/** 函数名称:closeDatabase* 功能说明:关闭数据库连接* 输入参数:无* 输出参数:无* 其他说明:无*/
void DatabaseCommon::closeDatabase()
{mDatabase.close();
}
/** 函数名称:execNormalSQL* 功能说明:执行通用SQL语句(SELECT除外)* 输入参数:SQL语句* 输出参数:无* 其他说明:无*/
bool DatabaseCommon::execNormalSQL(const QString &sqlString)
{QMutexLocker locker(&mMutex);if(!mDatabase.isOpen()){qCritical() << "Database is closed.";return false;}try{QSqlQuery query(mDatabase);if (!query.exec(sqlString)){throw query.lastError();}return true;}catch (const QSqlError &error){qCritical() << "Error:" << error.text();return false;}
}
/** 函数名称:execSelect* 功能说明:执行DQL语句(即SELECT)* 输入参数:SELECE语句* 输出参数:查询模型,获取结果* 其他说明:无*/
bool DatabaseCommon::execSelect(const QString &sqlString, QSqlQueryModel &model)
{QMutexLocker locker(&mMutex);if(!mDatabase.isOpen()){qCritical() << "Database is closed.";return false;}if(!sqlString.startsWith("SELECT", Qt::CaseInsensitive)){qCritical() << "Unsupported operation: " << sqlString;return false;}try{model.setQuery(sqlString, mDatabase);return true;}catch (const QException &ex){qCritical() << "Exception on model.setQuery: " << ex.what();qCritical() << model.lastError().text();return false;}
}
/** 函数名称:execTransaction* 功能说明:基于事务执行SQL语句(SELETE除外)* 输入参数:单个SQL语句* 输出参数:无* 其他说明:无*/
bool DatabaseCommon::execTransaction(const QString &sqlString)
{QMutexLocker locker(&mMutex);if(!mDatabase.isOpen()){qCritical() << "Database is closed.";return false;}if(sqlString.startsWith("SELECT", Qt::CaseInsensitive)){qCritical() << "Unsupported operation: " << sqlString;return false;}if (!mDatabase.transaction()){qCritical() << "Failed to begin transaction:" << mDatabase.lastError().text();return false;}QSqlQuery query(mDatabase);try{if (!query.exec(sqlString)){throw query.lastError();}// 可选:检查受影响行数if (sqlString.trimmed().startsWith("UPDATE", Qt::CaseInsensitive) && query.numRowsAffected() == 0){qWarning() << "Warning: No rows affected by:" << sqlString;}if (!mDatabase.commit()){throw mDatabase.lastError();}return true;}catch (const QSqlError &error){if (!mDatabase.rollback()){qCritical() << "Failed to rollback transaction:" << mDatabase.lastError().text();}qCritical() << "Transaction failed at command:" << query.lastQuery();qCritical() << "Error:" << error.text();return false;}
}
/** 函数名称:execTransaction* 功能说明:基于事务执行SQL语句(SELETE除外)* 输入参数:多个SQL语句* 输出参数:无* 其他说明:无*/
bool DatabaseCommon::execTransaction(const QStringList &sqlStrings)
{QMutexLocker locker(&mMutex);if(!mDatabase.isOpen()){qCritical() << "Database is closed.";return false;}if (!mDatabase.transaction()){qCritical() << "Failed to begin transaction:" << mDatabase.lastError().text();return false;}QSqlQuery query(mDatabase);try{foreach (const QString &sql, sqlStrings){if (!query.exec(sql)){throw query.lastError();}// 可选:检查受影响行数if (sql.trimmed().startsWith("UPDATE", Qt::CaseInsensitive) && query.numRowsAffected() == 0){qWarning() << "Warning: No rows affected by:" << sql;}}if (!mDatabase.commit()){throw mDatabase.lastError();}return true;}catch (const QSqlError &error){if (!mDatabase.rollback()){qCritical() << "Failed to rollback transaction:" << mDatabase.lastError().text();}qCritical() << "Transaction failed at command:" << query.lastQuery();qCritical() << "Error:" << error.text();return false;}
}

使用示例

QSqlDatabase::addDatabase("QSQLITE", "SysRun");//SysRun是数据库连接名
SysRunDatabase::Instance().setDatabase(QSqlDatabase::database("SysRun", false));
SysRunDatabase::Instance().setDatabaseName("123.db");//123.db是数据库文件名
/*打开数据库连接*/
if(!SysRunDatabase::Instance().openDatabase())
{return false;
}
//在此之后就可以增删改查

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/bicheng/83193.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI笔记 - 网络模型 - mobileNet

网络模型 mobileNet mobileNet V1网络结构深度可分离卷积空间可分![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/aff06377feac40b787cfc882be7c6e5d.png) 参考 mobileNet V1 网络结构 MobileNetV1可以理解为VGG中的标准卷积层换成深度可分离卷积 可分离卷积主要有…

第十五篇:MySQL 高级实战项目:构建高可用、可观测、性能优化一体化数据库平台

本篇聚焦于如何基于 MySQL 构建一个真正面向生产环境的数据库平台&#xff0c;集成高可用、可观测与性能调优三大核心能力&#xff0c;助力稳定、可扩展的系统运行。 一、项目背景与目标 在实际生产环境中&#xff0c;数据库系统需要应对以下挑战&#xff1a; 业务高速增长带来…

华为OD机试真题——文件目录大小(2025 A卷:100分)Java/python/JavaScript/C++/C语言/GO六种语言最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《文件目录大小》: 目录 题…

qwen 2.5 并行计算机制:依靠 PyTorch 和 Transformers 库的分布式能力

qwen 2.5 并行计算机制:依靠 PyTorch 和 Transformers 库的分布式能力 完整可运行代码: import torch import torch.nn.functional as F from transformers

TIDB创建索引失败 mkdir /tmp/tidb/tmp_ddl-4000/1370: no such file or directory.

TIDB创建索引失败&#xff1a;解决“mkdir /tmp/tidb/tmp_ddl-4000/1370: no such file or directory”问题 在使用 TIDB 数据库时&#xff0c;我们有时会遇到创建索引失败的问题。常见的错误信息为&#xff1a; mkdir /tmp/tidb/tmp_ddl-4000/1370: no such file or directo…

华为OD机试真题—— 最少数量线段覆盖/多线段数据压缩(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《最少数量线段覆盖/多线段数…

EasyRTC嵌入式音视频实时通话SDK助力AI与IoT智能硬件打造音视频交互多场景应用

一、引言​ 在数字化浪潮下&#xff0c;AI与IoT深度融合重塑智能硬件产业。实时音视频通信是智能硬件交互的核心&#xff0c;其性能关乎用户体验与场景拓展。EasyRTC嵌入式音视频实时通话SDK基于WebRTC技术&#xff0c;以轻量、易扩展的特性&#xff0c;为AI与IoT智能硬件融合…

第十四章 MQTT订阅

系列文章目录 系列文章目录 第一章 总体概述 第二章 在实体机上安装ubuntu 第三章 Windows远程连接ubuntu 第四章 使用Docker安装和运行EMQX 第五章 Docker卸载EMQX 第六章 EMQX客户端MQTTX Desktop的安装与使用 第七章 EMQX客户端MQTTX CLI的安装与使用 第八章 Wireshark工具…

【第4章 图像与视频】4.4 离屏 canvas

文章目录 前言为什么要使用 offscreenCanvas为什么要使用 OffscreenCanvas如何使用 OffscreenCanvas第一种使用方式第二种使用方式 计算时长超过多长时间适合用Web Worker 前言 在 Canvas 开发中&#xff0c;我们经常需要处理复杂的图形和动画&#xff0c;这些操作可能会影响页…

Go语言事件总线EventBus本地事件总线系统的完整实现框架

在Go语言中&#xff0c;EventBus是一种非常有用的工具&#xff0c;它通过事件驱动的编程方式&#xff0c;帮助开发者实现组件之间的解耦&#xff0c;提高代码的可维护性和扩展性。 背景 软件架构的发展需求&#xff1a;随着软件系统的规模和复杂度不断增大&#xff0c;传统的紧…

Go语言接口:灵活多态的核心机制

引言 Go语言的接口系统是其​​面向对象编程​​的核心&#xff0c;它摒弃了传统语言的类继承体系&#xff0c;采用独特的​​隐式实现​​和​​鸭子类型​​设计。这种设计使得Go接口既灵活又强大&#xff0c;成为构建松耦合系统的关键工具。本文将深入剖析Go接口的实现机制…

DeviceNET转EtherCAT网关:医院药房自动化的智能升级神经中枢

在现代医院药房自动化系统中&#xff0c;高效、精准、可靠的设备通信是保障患者用药安全与效率的核心。当面临既有支持DeviceNET协议的传感器、执行器&#xff08;如药盒状态传感器、机械臂限位开关&#xff09;需接入先进EtherCAT高速实时网络时&#xff0c;JH-DVN-ECT疆鸿智能…

android实现使用RecyclerView详细

显示页面代码&#xff1a;activity_category_inventory.xml代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android" xmlns:app"http://schemas.and…

【SpringBoot实战】优雅关闭服务

文章目录 一、什么是优雅关闭&#xff1f;二、优雅关闭的核心步骤三、SpringBoot优雅关闭实现四、关键注意事项1. 超时时间必须配置2. 信号支持局限性3. 特殊请求处理 五、底层实现原理六、总结 一、什么是优雅关闭&#xff1f; 优雅关闭&#xff08;Graceful Shutdown&#x…

C++哈希表:unordered系列容器详解

本节目标 1.unordered系列关联式容器 2.底层结构 3.模拟实现 4.哈希的应用 5.海量数据处理面试题 unordered系列关联式容器 在c98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可以达到logN&#xff0c;即最差的情况下需要比较红…

java操作服务器文件(把解析过的文件迁移到历史文件夹地下)

第一步导出依赖 <dependency><groupId>org.apache.sshd</groupId><artifactId>sshd-core</artifactId><version>2.13.0</version></dependency> 第二步写代码 public void moveFile( List<HmAnalysisFiles> hmAnalys…

Oracle OCP认证的技术定位怎么样?

一、引言&#xff1a;Oracle OCP认证的技术定位​ Oracle Certified Professional&#xff08;OCP&#xff09;认证是数据库领域含金量最高的国际认证之一&#xff0c;其核心价值在于培养具备企业级数据库全生命周期管理能力的专业人才。随着数字化转型加速&#xff0c;OCP认证…

TK海外抢单源码/指定卡单

​ 抢单源码&#xff0c;有指定派单&#xff0c;打针&#xff0c;这套二改过充值跳转客服 前端vue 后端php 两端分离 可二开 可以指定卡第几单&#xff0c;金额多少&#xff0c; 前后端开源 PHP7.2 MySQL5.6 前端要www.域名&#xff0c;后端要admin.域名 前端直接静态 伪静…

远程线程注入

注入简单来说就是让别人的程序执行 你想要让他执行的dll #include<iostream> #include<Windows.h> using namespace std;char szBuffer[] "C:\\Users\\20622\\source\\repos\\Dll1\\Debug\\test.dll"; //dll路径void RemoteThreadInject(DWORD Pid,PCH…

【Java实战】集合排序方法与长度获取方法辨析(易懂版)

一、排序方法 1. 对List排序的两种方式 方式一Collections.sort() List<Integer> numbers Arrays.asList(3,1,4,2); Collections.sort(numbers); // 直接修改原list → [1,2,3,4]方式二&#xff1a;list.sort()&#xff08;Java8推荐&#xff09; List<String>…