Qt 数据库QSqlDatabase使用记录

记录一些在QT中使用QSqlDatabase操作数据库时,需要注意的地方

创建数据库

bool CDBOperatorAbstract::_openDBConn(CDatabaseConfig config)
{QWriteLocker locker(&m_locker);QSqlDatabase db;if(QSqlDatabase::contains(m_connectionName)){db = QSqlDatabase::database(m_connectionName);QStringList tables = db.tables();if(db.isOpen() && tables.contains(config.m_databaseName)){m_isConnected = true;return true;}}else{// 此时目标数据库不一定存在,不指定数据库名,会默认连接到mysql的主数据库(mysql数据库)db = QSqlDatabase::addDatabase("QMYSQL",m_connectionName);db.setHostName(config.m_hostAddress);   // 数据库服务器IPdb.setPort(config.m_port);              // 端口号db.setUserName(config.m_userName);      // 用户名db.setPassword(config.m_userPwd);       // 密码}// 连接数据库if(!db.open()){qDebug() << db.lastError().text();m_isConnected = false;return false;}QSqlQuery query(db);QString strSql = QString("CREATE DATABASE IF NOT EXISTS `%1`").arg(config.m_databaseName);//执行建表语句,若执行成功if(query.exec(strSql)){//若查询语句有错if(query.lastError().isValid()){qDebug()<< query.lastError().text();m_isConnected = false;return false;}}else{m_isConnected = false;return false;}// 确认目标数据库创建成功,关闭之前打开的默认数据库
db.close();
// 重新设置连接的数据库名
db.setDatabaseName(config.m_databaseName);
// 重新打开数据库
if(!db.open())
{m_isConnected = false;return false;
}
else
{m_isConnected = true;return true;
}
}

在上述创建数据库的代码中有几个需要注意的地方:
1、一个QSqlDatabase对象表示的是一个数据库连接,而不是字面上的数据库(数据库连接与数据库的关系是:一个数据库连接可以通过修改配置连接到多个数据库,一个数据库也可以有多个数据库连接)

2、addDatabase()方法需要指定数据库驱动类型,如MySQL、SQLite……,如果没有指定连接名,将默认使用defaultConnection作为连接名。对于同一个连接,重复调用addDatabase(),会提示:

QSqlDatabasePrivate::addDatabase: duplicate connection name
‘qt_sql_default_connection’, old connection removed.

3、removeDatabase()删除数据库连接,需要在确保所有QSqlQuery查询操作执行完毕并且销毁,否则会提示:

QSqlDatabasePrivate::removeDatabase: connection ‘qt_sql_default_connection’ is still in use, all queries will cease to work.

4、在进行数据库连接时,目标数据库可能还不存在,这时候可以不指定数据库名进行连接,此会将连接到数据库服务器的主数据库,例如我使用的是MySQL数据库服务器,就会连接到mysql数据库
在这里插入图片描述

5、数据库连接建立成功后,创建目标数据库(不存在时才创建),确保目标数据库创建成功后,先关闭之前的数据库连接,设置数据库名称后再重新打开。(只有重新打开数据库连接,数据库配置才会生效)

多线程使用数据库

QSqlDatabase是非线程安全的,意味着在多线程环境下同时使用同一个数据库连接对象可能会导致竞态条件和数据一致性问题。因此,每个线程最好都维护一个独立的数据库连接,并且在同一个线程中创建、使用和关闭数据库连接。如果数据库连接有父对象,它和父对象也必须在同一个线程。
一般用QMap来管理线程和对应的数据库连接,可以用QMap<QThread*,QSqlDatabase*>来存储,也可以用QMap<QThread*,QString>来存储(存连接名)

由于程序可能在各个地方操作数据库,为了让数据库连接的创建和使用保持在同一个线程中,可以用QMetaObject::invokeMethod()将数据库的创建、使用、关闭都移动到数据库连接所在的线程中

bool CDBOperatorAbstract::checkIsInWorkThread()
{if(QThread::currentThread() == this->m_pThread)return true;elsereturn false;
}bool CDBOperatorAbstract::openDBConn(CDatabaseConfig config)
{if(checkIsInWorkThread()){return _openDBConn(config);}else{bool isOk = false;QMetaObject::invokeMethod(this,"_openDBConn",Qt::BlockingQueuedConnection,Q_RETURN_ARG(bool,isOk),Q_ARG(CDatabaseConfig,config));return isOk;}
}

用BlockingQueuedConnection的连接方式,会将目标函数放在接收者的生存线程中执行,并且阻塞发送者所在的线程,直到目标函数执行完毕。

增删改查

numRowsAffected()
这个函数返回最后一个执行的 SQL 查询语句所影响的行数。通常用于 INSERT、UPDATE 或 DELETE 查询之后,用来确定有多少行受到了影响。返回值是一个整数。

lastInsertId()
这个函数用于在主键自增的情况下,获取最后一次 INSERT 操作生成的主键,返回值为QVariant类型,需要根据主键实际的类型进行转换。

size()
这个函数用于获取当前查询结果集中的记录数。例如执行 SELECT 查询后需要确定返回的记录数量。返回值是一个整数。

isValid()
这个函数用于检查 QSqlQuery 对象是否有效,即它是否正常地初始化以执行 SQL 查询。

一个值得借鉴的多线程数据库连接管理方式

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

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

相关文章

Android解决报错 superclass access check failed: class

Android解决报错 superclass access check failed: class 前言&#xff1a; 最近在打开之前的项目demo时&#xff0c;出现一个错误Cause: superclass access check failed: class butterknife.compiler.ButterKnifeProcessor$RScanner 1.错误信息如下&#xff1a; Executio…

微积分-三角函数2

三角函数 在上一节中&#xff0c;讨论了如何在直角三角形中定义三角函数&#xff0c;限制让我们扩展三角函数的定义域。 事实上我们可以取任意角的正弦和余弦&#xff0c;而不只是局限于 0 0 0~ π 2 \frac{\pi}{2} 2π​当中。 当然需要注意的是&#xff0c;正切函数对不是对…

大模型下开源文档解析工具总结及技术思考

1 基于文档解析工具的方法 pdf解析工具 导图一览&#xff1a; PyPDF2提取txt&#xff1a; import PyPDF2 def extract_text_from_pdf(pdf_path):with open(pdf_path, rb) as file:pdf_reader PyPDF2.PdfFileReader(file)num_pages pdf_reader.numPagestext ""f…

【MySQL学习之基础篇】多表查询

文章目录 1. 多表关系1.1. 一对多1.2. 多对多1.3. 一对一 2. 多表查询概述2.1. 数据准备2.2. 概述 3. 查询的分类3.1. 内连接查询3.2. 外连接查询3.3. 自连接3.3.1. 自连接查询3.3.2. 联合查询 3.4. 子查询3.4.1. 概述3.4.2. 标量子查询3.4.3. 列子查询3.4.4. 行子查询3.4.5. 表…

pycharm某个xxx.sh文件显示问号,无法编辑

文章目录 pycharm某个xxx.sh文件显示问号,无法编辑其他参考 pycharm某个xxx.sh文件显示问号,无法编辑 问题描述&#xff1a;pycharm某个xxx.sh文件显示问号,无法编辑 问题分析&#xff1a; pycharm无法识别文件类型。 问题解决&#xff1a; 在pycharm中选中该文件&#xff0…

jmeter前置/后置处理器耗时问题

1. 问题&#xff1a; 需要前置处理器处理一个较为复杂的请求体&#xff0c;循环和判断较多&#xff0c;所以想要验证一下&#xff0c;jmeter在统计业务响应时间时&#xff0c;是否包括前置/后置处理器耗时问题 2. 准备&#xff1a; 创建一个jsr请求&#xff0c;sleep 10毫秒…

TS类型体操-简单-实现pick

文章目录 问题描述举例实现 问题描述 不使用 Pick<T, K> &#xff0c;实现 TS 内置的 Pick<T, K> 的功能。 从类型T 中选出符合 K 的属性&#xff0c;构造一个新的类型。 举例 interface Todo {title: stringdescription: stringcompleted: boolean }type TodoPre…

爆火的“数字人”,你还不知道吗?

数字人是一种基于人工智能技术创建的虚拟实体&#xff0c;具有高度智能化和交互性。他们可以像真正的人类一样思考、学习和表达情感&#xff0c;与人类进行对话和互动。数字人的出现在电影中已经有了一些令人难忘的片段。 首先&#xff0c;值得一提的是电影《阿凡达》中的数字…

10、神秘的“位移主题”

神秘的“位移主题” 1、什么是位移主题2、位移主题的消息格式3、位移主题是怎么被创建的4、什么地方会用到位移主题5、位移主题的删除机制 本章主题是&#xff1a;Kafka 中的内部主题&#xff08;Internal Topic&#xff09;__consumer_offsets。 __consumer_offsets 在 Kafka …

【玩转TableAgent数据智能分析】TableAgent全功能详解及多领域数据分析实践(下)数据分析过程及总结展望

6 TableAgent的数据分析过程解析 TableAgent的整个分析过程包括以下步骤&#xff0c;形成一个有机结构&#xff0c;让我们理清其工作原理。 6.1 Data Graph阶段 TableAgent首先绘制数据图&#xff0c;以解决问题。这个图形表示了问题的分解和细化&#xff0c;将大问题分解成…

紫光展锐CEO任奇伟博士:展锐5G芯筑基当下,迈向未来

12月5日&#xff0c;紫光集团执行副总裁、紫光展锐CEO任奇伟博士受邀出席2023世界5G大会5G产业强基发展论坛&#xff0c;发表了题为《展锐5G芯&#xff1a;筑基当下&#xff0c;迈向未来》的演讲。 ​ 世界5G大会由国务院批准&#xff0c;国家发展改革委、科技部、工信部与地方…

案例064:基于微信小程序的考研论坛设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…