Qt 数据库QSqlDatabase使用示例

 更新时间:2023年12月15日 15:45:22   作者:kahh  
本文主要介绍了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 查询。

到此这篇关于Qt 数据库QSqlDatabase使用示例的文章就介绍到这了,更多相关Qt QSqlDatabase内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • OpenGL绘制三次Bezier曲线

    OpenGL绘制三次Bezier曲线

    这篇文章主要为大家详细介绍了OpenGL绘制三次Bezier曲线,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • C++ pimpl机制详细讲解

    C++ pimpl机制详细讲解

    PIMPL 是 C++ 中的一个编程技巧,意思为指向实现的指针。具体操作是把类的实现细节放到一个单独的类中,并用一个指针进行访问
    2022-08-08
  • 基于c中使用ftruncate()前需要fflush(),使用后需要rewind()的深入探讨

    基于c中使用ftruncate()前需要fflush(),使用后需要rewind()的深入探讨

    本篇文章是对在c中使用ftruncate()前需要fflush(),使用后需要rewind()进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • 随机数字去掉重复和排序的方法

    随机数字去掉重复和排序的方法

    用计算机随机生成了N个0到1000000000(包含0和1000000000)之间的随机整数(N≤5000000),对于其中重复的数字,只保留一个,把其余相同的数去掉。然后再把这些数从小到大排序。
    2013-03-03
  • 基于C语言实现的迷宫算法示例

    基于C语言实现的迷宫算法示例

    这篇文章主要介绍了基于C语言实现的迷宫算法,结合具体实例形式分析了C语言解决迷宫问题算法的实现技巧与相关注意事项,需要的朋友可以参考下
    2017-09-09
  • 详解C++11中的右值引用与移动语义

    详解C++11中的右值引用与移动语义

    本篇文章主要介绍了详解C++11中的右值引用与移动语义,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • C++单链表实现大数加法

    C++单链表实现大数加法

    这篇文章主要为大家详细介绍了C++单链表实现大数加法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • C语言实现一个多线程委托模型的示例详解

    C语言实现一个多线程委托模型的示例详解

    这篇文章主要介绍了C语言实现一个多线程委托模型,这就是一个使用C语言实现多线程委托模型的例子,其中包含boss线程和worker线程,可以处理工作线程的异常情况,需要的朋友可以参考下
    2023-06-06
  • vscode配置C++环境的图文教程

    vscode配置C++环境的图文教程

    这篇文章主要介绍了vscode配置C++环境的教程图文详解,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • 判断整数序列是否为二元查找树的后序遍历结果的解决方法

    判断整数序列是否为二元查找树的后序遍历结果的解决方法

    本篇文章是对判断整数序列是否为二元查找树的后序遍历结果的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05

最新评论