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);   // 数据库服务器IP
        db.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;
    else
        return 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 查询。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CloudFlare 优选ip 和 优选域名的获取方法

1.CloudFlare优选IP网站:【链接直达】 2.CloudFlare 优选IP工具&#xff1a;【开源软件】 3.CloudFlare 优选域名&#xff1a;【GitHub开源工具】 4.CF优选域名推荐&#xff1a; time.cloudflare.com shopify.com time.is icook.hk icook.tw ip.sb japan.com malaysia.com rus…

深入学习《大学计算机》系列之第1章 1.2节——问题描述与抽象

一.欢迎来到我的酒馆 第1章 1.2节&#xff0c;问题描述与抽象。 目录 一.欢迎来到我的酒馆二.问题描述、抽象与建模1.什么是抽象2.为什么要抽象3.什么是建模4.建什么模 三.面向计算机的问题分析四.总结 二.问题描述、抽象与建模 什么是抽象&#xff1f;为什么要抽象&#xff1f…

Chrome限制第三方Cookie:未来无法再追踪你看过哪些敏感的“色色”内容了

当我们在浏览网络的时候&#xff0c;常听到「Cookie」这个词&#xff0c;但许多人可能不太清楚它到底是什么。最近&#xff0c;Google 宣布了一项重要更新&#xff0c;Google Chrome 将减少对第三方cookie 的支持&#xff0c;以提高用户隐私保护。 下面我会解释一下这个改变对…

打印机设置发票收据打印

由于各种打印机型号不一样&#xff0c;设置方式打印效果出入也很大&#xff0c;存在打印不全问题&#xff0c;发票右侧小数点后面的数字打印不出来、位置靠上下左右登问题&#xff0c;比较通用的设置方式如下&#xff1a; 首先找到控制面板&#xff0c;找到设备和打印机 进入到…

Aurora8B10B(二) 从手册和仿真学习Aurora8B10B

一. 简介 在上篇文章中&#xff0c;主要结合IP配置界面介绍了一下Aurora8B10B&#xff0c;这篇文章将结合文档来学习一下Aurora8B10B内部的一些细节 和 相关的时序吧。文档主要是参考的是这个 pg046-aurora-8b10b-en-us-11.1 二. Aurora8B10B内部细节 在手册上&#xff0c;对…

弧形导轨的精度等级

为符合工控自动化生产制造必须&#xff0c;弧形导轨在运输武器装备领域应时而生&#xff0c;并已在电子生产制造、手机上、半导体材料、动力锂电池等领域获得广泛运用。其中&#xff0c;弧形导轨的精度等级是评估其运动精度的重要指标&#xff0c;通常包括制造精度和运行精度两…

低代码核心能力详解:简化应用开发的新思路

低代码平台作为一种快速地应用开发解决方法&#xff0c;为中小企业实现数字化转型提供了机会。但是&#xff0c;对于一些刚开始触碰低代码平台的企业来说&#xff0c;了解其核心能力是很重要的。本文将详细分析低代码平台的核心能力&#xff0c;并在挑选低代码平台以前为中小企…

【星环云课堂大数据实验】InceptorSQL使用方法

文章目录 一、InceptorSQL概述二、实验环境三、实验准备四、实验目的五、实验步骤5.1 使用Waterdrop连接Inceptor5.2、WordCount5.3、外部表与内部表5.4、普通ORC表5.5、创建ORC事务表5.6、创建ORC分区表5.7、创建ORC分区分桶表 一、InceptorSQL概述 InceptorSQL是一个**分布式…

数据结构-迷宫问题

文章目录 1、题目描述2、题目分析3、代码实现 1、题目描述 题目链接&#xff1a;迷宫问题 、 注意不能斜着走&#xff01; 2、题目分析 &#xff08;1&#xff09;0为可以走&#xff0c;1不能走且只有唯一一条通路 &#xff08;2&#xff09;我们可以通过判断上下左右来确定…

开酸奶店为何失败,5年创业者和你分享赚钱经验

我是张峻荣&#xff0c;开鲜奶吧已经有 5 年时间了&#xff0c;在自媒体创业板块也是小有名气&#xff0c;经常在网络上分享一些酸奶店的创业知识。今天我要和大家分享的是开酸奶店失败的原因&#xff0c;以及如何赚钱的经验。 5 年前&#xff0c;是我第一次创业失败&#xff…

activiti并行网关执行时每个关联表的变化

activiti并行网关执行时每个关联表的变化 文章目录 &#x1f50a;流程图&#x1f4c6; 通过请假节点&#x1f4d5;通过一个并行节点&#x1f5a5;️再通过一个并行节点&#x1f516;再通过校长任务&#x1f58a;️最后总结 &#x1f50a;流程图 &#x1f4c6; 通过请假节点 &l…

口袋参谋:新品上架,如何获取更多免费流量?

​新品上架 如何获得更多的免费流量&#xff1f; 我相信 这是99.999%的商家&#xff0c;都关心的问题&#xff01; 今天我就来和大家好好说道说道。 01 流量的组成 新品本身是没有权重的&#xff0c;买家搜不到我们。 如果想要获得更多的免费流量&#xff0c;我们就要知道…

千梦网创:逮住一闪而过的机会疯狂摩擦

我这个人平时想的就多&#xff0c;睡觉也在想事情&#xff0c;有时候睡觉里想的事情往往都是很纯粹的、很绝妙的&#xff0c;但是经常性一醒过来就忘了&#xff0c;再去回忆怎么也想不起来了。 灵感只在特定的环境下产生&#xff0c;这类环境是不可再生和模拟的。 机会只因特…

17. 常用类

1.String类 1).什么是字符串? 字符串是由多个字符组成的一串数据(字符序列),字符串可以看成是字符数组. 2).String类的概述 String 类代表字符串。Java 程序中的所有字符串字面值&#xff08;如 “abc” &#xff09;都作为此类的实例实现。 字符串是常量&#xff1b;它们…

connect: Network is unreachable问题解决

第一步&#xff1a;查看ifcfg-ens33配置文件 cd /etc/sysconfig/network-scripts/ cat ifcfg-ens33 发现问题&#xff1a;GATEWAY写错成GATWAY 第二步&#xff1a;修改 vim ifcfg-ens33 第三步&#xff1a;检测是否成功 ping baidu.com 成功&#xff01;

【Unity动画】实现不同的肢体动作自由搭配播放Layer+Avatar Mask

这个教程教你学会使用Unity 动画层配合布偶遮罩&#xff08;AvaterMask&#xff09; 实现从2个动画身上只保留部分肢体动作&#xff0c;然后搭配播放 例如&#xff1a;一个正常跑的动画片段&#xff0c;我只保留腿部动作&#xff0c;形成一个层叫Run_leg 然后在从一个攻击动作…

Java-File类与IO流(2)

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

b-tree b+tree两种区别

Btree多了叶子节点&#xff0c;并可以看到多了个箭头&#xff0c;这样查询比如大于>2,Btree更容易。而b--tree则要返到第一层、第二层才可以最得所有>2的数据

【STL容器】详解vector的使用和模拟实现

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; STL函数专栏 &#x1f319;请不要相信胜利就像山坡上的蒲公英一…

自媒体新闻中心-后台管理端

0.本节内容说明 本节主要是一个功能概述&#xff0c;了解清楚这个这个后台管理端做的什么&#xff0c;以及实现的思路&#xff0c;具体的实现代码部分&#xff0c;后面讲解 1.后台功能概述 登陆: 账号密码登陆&#xff0c;或者是账号人脸进行登陆内容审核&#xff1a;对于用户…