本文将详细介绍如何在Qt应用程序中集成MySQL数据库,并封装实现好用的mysql数据库操作类。包括环境准备、连接数据库、执行查询及异常处理等关键步骤,同时包含mysql驱动的编译。分享给有需要的小伙伴,喜欢的可以点击收藏。
目录
Qt提供了QtSql模块来进行独立于平台的数据库操作,这里的“平台”既包括操作系统平台,也包括各个数据库平台。Qt使用一个QDatabase表示一个数据库连接。在底层,Qt使用不同的驱动程序来与不同的数据库API进行交互。
通常Qt只默认搭载了QSqlLite驱动程序,如果需要使用其他数据库,需要下载相应的数据库驱动,如mysql的为 qsqlmysql.dll,同时还需要mysql的客户端库libmysql.dll。
在连接数据库之前可以使用QSqlDatabase::drivers()
查看本机Qt已经支持的数据库驱动。
环境准备
1.安装MySQL数据库:首先确保你的系统中安装了MySQL服务器,并创建好数据库和表结构。
2.安装Qt开发环境:安装Qt Creator及Qt库,确保包含SQL驱动模块。
注意:Qt默认并不包括MySQL驱动,需要手动构建。在QT安装目录(如Qt5.12.11\5.12.11\msvc2015_64\plugins\sqldrivers)里找,是否有qsqlmysql.dll和qsqlmysqld.dll.
如果没有则需要基于QT源码从新构建,构建好后把qsqlmysql.dll放入plugins\sqldrivers目录中。如果不存在该库,则程序执行会报QSqlDatabase: QMYSQL driver not loaded的错误。
如果要构建QMYSQL,需安装Qt源代码,并确保你的系统中安装了MySQL服务器或至少安装了MySQL Connector/C++,因为构建过程需要MySQL的头文件和库文件。
可以通过以下方式查看支持哪些驱动:
qDebug()<<"support drivers:"<<QSqlDatabase::drivers();
3.安装MySQL的c/c++的Connector(MySQL客户端库):对于Qt 5.12及以上版本,MySQL驱动可能已内置,但若缺失,需下载MySQL Connector/C++并安装,确保Qt能找到libmysql动态库。(libmysql.dll动态库。链接:MySQL :: Download MySQL Connector/C (Archived Versions))
将压缩包解压,将lib文件夹下的libmysql.dll和libmysql.lib文件拷贝到Qt的安装目录的bin文件夹下即可。
项目配置
在你的Qt项目文件(.pro)中添加如下行以启用SQL模块:
QT += sql
简单使用
编写代码连接数据库:
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
void connectToDatabase() {
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("testdb");
db.setUserName("root");
db.setPassword("password");
if (!db.open()) {
qDebug() << "Failed to connect to database:" << db.lastError().text();
} else {
qDebug() << "Connected to database!";
}
}
简单示例
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
void connectToDatabase() {
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("testdb");
db.setUserName("root");
db.setPassword("password");
if (!db.open()) {
qDebug() << "Failed to connect to database:" << db.lastError().text();
} else {
qDebug() << "Connected to database!";
}
}
bool createTable() {
QSqlQuery query;
bool success = query.exec("CREATE TABLE person (id INT PRIMARY KEY, name VARCHAR(40))");
if (!success) {
qDebug() << "Failed to create table:" << query.lastError().text();
}
return success;
}
bool insertRecord(int id, const QString &name) {
QSqlQuery query;
query.prepare("INSERT INTO person (id, name) VALUES (:id, :name)");
query.bindValue(":id", id);
query.bindValue(":name", name);
bool success = query.exec();
if (!success) {
qDebug() << "Failed to insert record:" << query.lastError().text();
}
return success;
}
void queryRecords() {
QSqlQuery query("SELECT id, name FROM person");
while (query.next()) {
int id = query.value(0).toInt();
QString name = query.value(1).toString();
qDebug() << id << name;
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
connectToDatabase();
createTable();
insertRecord(1, "Alice");
insertRecord(2, "Bob");
queryRecords();
return a.exec();
}
模块类封装
直接使用不太好用,这里做一个模块类封装,变得更好用啦,接口变得简单清晰。如果不封装,则原始是使用大概如下:
QSqlQuery query(QSqlDatabase::database(connectionName, true));
query.prepare("insert into test(name,age) values(:nameL,:ageL)");
QStringList namelist;
namelist<<"Tt"<<"Pp"<<"Kk";
query.bindValue(":nameL",namelist);
QVariantList agelist;
agelist<<40<<50<<60;
query.bindValue(":ageL",agelist);
if(!query.execBatch()){
qDebug()<<"数据插入失败: "<<query.lastError().text();
}else{
qDebug()<<"数据插入成功!";
}
可以看到使用比较繁琐,封装后的模块代码如下:
#include "mysqldb.h"
#include <QDebug>
#include <QUuid>
mysqlDb::mysqlDb() {
qDebug()<<"support drivers:"<<QSqlDatabase::drivers();
}
mysqlDb::~mysqlDb() {
disConnectSql();
}
//打开连接
bool mysqlDb::connectSql(const QString &dbName) {
mdbName_= dbName;
db = QSqlDatabase::database(connectionName);
if(!db.isValid()) {
QUuid qUuid = QUuid::createUuid();
QString strUuid = qUuid.toString();
connectionName = QString("mysql-%1").arg(strUuid);
db = QSqlDatabase::addDatabase("QMYSQL",connectionName);
db.setHostName(mhost_); //根据实际情况设置主机名
db.setPort(mport_);
db.setDatabaseName(dbName);
db.setUserName(muser_); //根据实际情况设置用户名
db.setPassword(mpwd_); //根据实际情况设置密码
db.setConnectOptions("MYSQL_OPT_RECONNECT=1"); // 支持断线重连
if (!db.open()) {
qWarning("Failed to open database: %s", qPrintable(db.lastError().text()));
return false;
}
}
return true;
}
//打开连接
bool mysqlDb::connectSql(const QString &host, int port, const QString &dbName, const QString &userName, const QString &password) {
mhost_= host;
mport_= port;
mdbName_= dbName;
muser_= userName;
mpwd_ = password;
db = QSqlDatabase::database(connectionName);
if(!db.isValid()) {
QUuid qUuid = QUuid::createUuid();
QString strUuid = qUuid.toString();
connectionName = QString("mysql-%1").arg(strUuid);
db = QSqlDatabase::addDatabase("QMYSQL",connectionName);
db.setHostName(host); //根据实际情况设置主机名
db.setPort(port);
db.setDatabaseName(dbName);
db.setUserName(userName); //根据实际情况设置用户名
db.setPassword(password); //根据实际情况设置密码
db.setConnectOptions("MYSQL_OPT_RECONNECT=1"); // 支持断线重连
if (!db.open()) {
qWarning("Failed to open database: %s", qPrintable(db.lastError().text()));
return false;
}
}
return true;
}
//关闭连接
bool mysqlDb::disConnectSql() {
db = QSqlDatabase::database(connectionName);
if(!db.isValid()) {
return true;
}
db.close();
QSqlDatabase::removeDatabase(connectionName);
connectionName = "";
return true;
}
//错误打印
void mysqlDb::errorSql(QString sql) {
errorSqlText = sql;
qCritical("%s", qPrintable(errorSqlText));
}
//获取错误的数据库语句
QString mysqlDb::getErrorSql() {
if(connectionName.isEmpty()) {
return "db not setting";
}
return errorSqlText;
}
void mysqlDb::setMdbName(const QString &mdbName)
{
mdbName_ = mdbName;
}
void mysqlDb::setMpwd(const QString &mpwd)
{
mpwd_ = mpwd;
}
void mysqlDb::setMuser(const QString &muser)
{
muser_ = muser;
}
void mysqlDb::setMhost(const QString &mhost)
{
mhost_ = mhost;
}
void mysqlDb::setMport(int mport)
{
mport_ = mport;
}
//执行sql语句,不获取结果
bool mysqlDb::queryExec( QString queryStr) {
if(connectionName.isEmpty()) {
if(!connectSql(mhost_,mport_,mdbName_,muser_,mpwd_)) {
return false;
}
}
QSqlQuery query(QSqlDatabase::database(connectionName, true));
if(!query.exec(queryStr)) {
errorSql(queryStr);
return false;
}
return true;
}
//执行sql语句,并获取结果
bool mysqlDb::queryExec( QString queryStr, QList<QHash<QString, QString>> &data) {
data.clear();
if(connectionName.isEmpty()) {
if(!connectSql(mhost_,mport_,mdbName_,muser_,mpwd_)) {
return false;
}
}
QSqlQuery query(QSqlDatabase::database(connectionName, true));
if(!query.exec(queryStr)) {
errorSql(queryStr);
return false;
}
QSqlRecord rec = query.record();
while(query.next()) {
QHash<QString, QString> rowData;
for(int i = 0; i < rec.count(); i++) {
QVariant::Type ty = query.value(i).type();
if(QVariant::Type::Date == ty) {
QDate temp = query.value(i).toDate();
rowData[rec.fieldName(i)] = temp.toString("yyyy-MM-dd");
} else if(QVariant::Type::Time == ty) {
QTime temp = query.value(i).toTime();
rowData[rec.fieldName(i)] = temp.toString("hh:mm:ss");
} else if(QVariant::Type::DateTime == ty) {
QDateTime temp = query.value(i).toDateTime();
rowData[rec.fieldName(i)] = temp.toString("yyyy-MM-dd hh:mm:ss");
} else {
rowData[rec.fieldName(i)] = query.value(i).toString();
}
}
data.append(rowData);
}
return true;
}
//获取数据
bool mysqlDb::getData(QString tableName, QHash<QString, QString> &data, QString sqlWhere) {
data.clear();
QList<QHash<QString, QString>> dataList;
if(!getData(tableName, dataList, sqlWhere)) {
return false;
}
if(dataList.count() > 0) {
data = dataList[0];
}
return true;
}
//获取数据
bool mysqlDb::getData( QString tableName, QList<QHash<QString, QString>> &data, QString sqlWhere) {
QString queryStr = "select * from " + tableName;
if(!sqlWhere.isEmpty()) {
queryStr += " " + sqlWhere;
}
return queryExec(queryStr, data);
}
//获取数据
bool mysqlDb::getData(QString tableName, QHash<QString, QString> columndata, QList<QHash<QString, QString>> &data, QString sqlWhere) {
QString colunmStr;
if(columndata.count() == 0) {
colunmStr = "*";
} else {
QStringList keys = columndata.keys();
for(auto key : keys) {
QString column = QString("%1 AS %2").arg(key).arg(columndata[key]);
if(!colunmStr.isEmpty()) {
colunmStr += ",";
}
colunmStr += column;
}
}
QString queryStr = QString("SELECT %1 FROM %2 %3").arg(colunmStr).arg(tableName).arg(sqlWhere);
return queryExec(queryStr, data);
}
//增加
bool mysqlDb::addData(QString tableName, QHash<QString, QString> data) {
if(data.isEmpty()) {
return false;
}
QString queryStr = "INSERT INTO " + tableName + " ";
QString fieldStr = "(", valueStr = "VALUES(";
QHash<QString, QString>::iterator it;
for(it = data.begin(); it != data.end(); ++it) {
fieldStr += it.key() + ",";
valueStr += "'" + it.value() + "',";
}
fieldStr = fieldStr.left(fieldStr.length() - 1);
valueStr = valueStr.left(valueStr.length() - 1);
fieldStr += ")";
valueStr += ")";
queryStr += fieldStr + " " + valueStr;
return queryExec(queryStr);
}
//删除
bool mysqlDb::delData(QString tableName, QString sqlWhere) {
QString queryStr = "DELETE FROM " + tableName;
if(!sqlWhere.isEmpty()) {
queryStr += " " + sqlWhere;
}
return queryExec(queryStr);
}
//修改
bool mysqlDb::updateData( QString tableName, QHash<QString, QString> data, QString sqlWhere) {
QString queryStr = "UPDATE " + tableName + " ";
QHash<QString, QString>::iterator it;
QString setStr = "SET ";
for(it = data.begin(); it != data.end(); ++it) {
setStr += it.key() + "='" + it.value() + "'";
setStr += ",";
}
setStr = setStr.left(setStr.length() - 1);
queryStr += setStr;
if(!sqlWhere.isEmpty()) {
queryStr += " " + sqlWhere;
}
return queryExec(queryStr);
}
bool mysqlDb::transaction() {
if(connectionName.isEmpty()) {
return false;
}
return db.transaction();
}
bool mysqlDb::commit() {
if(connectionName.isEmpty()) {
return false;
}
return db.commit();
}
#ifndef MYSQLDB_H
#define MYSQLDB_H
#include <QDir>
#include <QDate>
#include <QDateTime>
#include <QFileInfo>
#include <QString>
#include <QTime>
#include <QSqlDatabase>
#include <QSqlRecord>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>
class mysqlDb
{
public:
mysqlDb();
~mysqlDb();
public:
bool connectSql(const QString &dbName);//打开连接
bool connectSql(const QString &host, int port, const QString &dbName, const QString &userName, const QString &password);//打开连接
bool disConnectSql();//关闭连接
bool queryExec(QString sqlStr);//执行sql语句,不获取结果
bool queryExec(QString sqlStr,QList<QHash<QString,QString>> &data);//执行sql语句,并获取结果
bool getData(QString tableName,QHash<QString,QString> &data,QString sqlWhere=""); //获取数据
bool getData(QString table,QList<QHash<QString,QString>> &data,QString sqlWhere=""); //获取数据
bool getData(QString tableName,QHash<QString,QString> columndata,QList<QHash<QString,QString>> &data,QString sqlWhere=""); //获取数据
bool addData(QString tableName,QHash<QString,QString> data);//增加
bool delData(QString tableName,QString sqlWhere);//删除
bool updateData(QString tableName,QHash<QString,QString> data,QString sqlWhere="");//修改
bool transaction();
bool commit();
QString getErrorSql();//获取错误的数据库语句
void setMhost(const QString &mhost);
void setMport(int mport);
void setMdbName(const QString &mdbName);
void setMuser(const QString &muser);
void setMpwd(const QString &mpwd);
private:
QSqlDatabase db;
QString connectionName="";
QString errorSqlText;//错误语句
QString mdbName_="";
QString mhost_ = "localhost";
int mport_ = 3306;
QString muser_="";
QString mpwd_="";
private:
void errorSql(QString sql);//错误打印
};
#endif // MYSQLDB_H
如何使用
void MainWindow::on_btn_test_clicked()
{
mysqlDb* db = new mysqlDb();
db->setMhost("111.178.126.10");
db->setMuser("xxxxxx");
db->setMpwd("xxxxxx");
bool ret = db->openSql("test");
if(ret){
qDebug("connect ok");
//插入数据
QHash<QString, QString> user;
user.insert("name","yang");
user.insert("age","30");
ret = db->addData("user",user);
if(ret){
qDebug("insert ok");
}else{
qDebug("insert error");
}
//读取数据
QList<QHash<QString, QString>> data;
ret = db->getData("user",data,"");
if(ret){
qDebug("get ok");
for(auto d:data){
qDebug(d["user"].toStdString().c_str());
qDebug(d["age"].toStdString().c_str());
}
}else{
qDebug("get error");
}
//更新
QHash<QString, QString> update;
update.insert("age","35");
ret = db->updateData("user",update,"where age = 30");
if(ret){
qDebug("updateData ok");
}else{
qDebug("updateData error");
}
//删除
ret = db->delData("user","where age = 32");
if(ret){
qDebug("delete ok");
}else{
qDebug("delete error");
}
}else{
qDebug("connect error");
}
}
附qsqlmysql库的构建
如果已经有该库,以下步骤可忽略。该库位置在
Qt5.xx\5.xx\msvc20xx_\plugins\sqldrivers
qsqlmysql库是Qt框架中用于连接MySQL数据库的一个插件库。它是Qt SQL模块的一部分,专门设计用于提供对MySQL数据库的支持。
前提条件
- 安装Qt:确保你已经安装了Qt和Qt Creator。
- 安装MySQL客户端库:
- Windows环境下,可以直接下载 MySQL C API 开发包 (MySQL Connector/C)。
- Linux环境,可通过包管理器安装(例如
sudo apt-get install libmysqlclient-dev
)。 - macOS环境,可通过Homebrew安装(例如
brew install mysql-client
)。
- 下载QT相应版本的源码,比如我的是Qt5.14.2。下载地址:https://download.qt.io/
构建步骤
1. 查找Qt的安装路径和编译器
- 确认你的Qt安装路径。例如:
C:\Qt\5.x.x\mingwxx_32
- 确认你使用的编译器,如
MinGW
或MSVC
,以及其路径。 - QT的源码不用全解压,只需要qtbase这个文件夹下的全部内容。
2. 设置环境变量
- 将Qt的编译工具(如
qmake
)添加到系统的PATH
变量中。
3. 获取MySQL开发库
- 确保你已经下载并解压了 MySQL Connector/C 用于 Windows 系统;在Linux和macOS系统上安装相应的开发库会自动设置好的路径。
4. 构建 qsqlmysql
插件
使用Qtcreator打开D:\Qt\qtbase\src\plugins\sqldrivers\mysql\mysql.pro工程文件。
打开工程后,会报错:Cannot read qtsqldrivers-config.pri: No such file or directory
接下来需要对mysql.pro文件和它上一级的qsqldriverbase.pri文件做出修改:
修改qsqldriverbase.pri
QT = core core-private sql-private
# For QMAKE_USE in the parent projects.
#注释到这个
#include($$shadowed($$PWD)/qtsqldrivers-config.pri)
#新增加这个
include(./configure.pri)
PLUGIN_TYPE = sqldrivers
load(qt_plugin)
DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
修改 mysql.pro:
TARGET = qsqlmysql
HEADERS += $$PWD/qsql_mysql_p.h
SOURCES += $$PWD/qsql_mysql.cpp $$PWD/main.cpp
#注释到这个
#QMAKE_USE += mysql
OTHER_FILES += mysql.json
PLUGIN_CLASS_NAME = QMYSQLDriverPlugin
#以下为新增
#!!mysql的lib路径
LIBS += D:\Qt\mysql-connector-c-6.1.11-winx64/lib/libmysql.lib
#!!mysql的include路径
INCLUDEPATH += $$quote(D:\Qt\mysql-connector-c-6.1.11-winx64/include)
#!!mysql的include路径
DEPENDPATH += $$quote(D:\Qt\mysql-connector-c-6.1.11-winx64/include)
include(../qsqldriverbase.pri)
#!!设置编译好的qmysql.dll放置的目录
DESTDIR = ../mysql/mysqlDll
5. 将编译好的插件拷贝到合适的位置
- 将编译得到的
qsqlmysql.dll
(或libqsqlmysql.so
或libqsqlmysql.dylib
)放到Qt的插件目录下。例如C:\Qt\5.x.x\mingwxx_64\plugins\sqldrivers
(Windows)或/path/to/qt/plugins/sqldrivers
(Linux和macOS)。
注意事项
- 版本匹配:请确保你的 MySQL 客户端库版本与 MySQL 服务器版本兼容,同时确保与 Qt 使用的编译器版本一致。
- 路径问题:在运行示例程序时,所有路径要使用绝对路径或将相关路径加入到环境变量中以确保 Qt 能够找到相应的库文件。
- 权限问题:在Linux和macOS环境下,可能需要使用
sudo
来执行某些命令以拥有足够的权限。
按照上述步骤,你应该能够成功构建并使用 qsqlmysql
插件来连接 MySQL 数据库。
最后,附上编译好的mysql驱动,含windows和mac版本的(5.14.2,5.15.2,6.5.3)
链接如下:
https://pan.baidu.com/s/1m15DbFuFTtXfEyqyOS2cew
提取码: 2o2s
其他资源
https://www.cnblogs.com/zhuchunlin/p/16485933.html
QT连接MYSQL(保姆级成功案例)_qt mysql-CSDN博客
QT学习之路——Qt QMySQL driver not loaded问题(笔记)_qsqldatabase: qmysql driver not loaded qsqldatabas-CSDN博客
MySQL :: Download MySQL Connector/C (Archived Versions)
QT加载mysql失败,重新构建mysql源文件_qt重新加载资源文件-CSDN博客
https://www.cnblogs.com/flygreen/p/18029637
Qt连接mysql数据库_不能找到qtsqldrivers-config.pri-CSDN博客
Linux下Qt 5.15.2源码下载及编译_qt5 linux 源码下载-CSDN博客
qt creator mysql_qt creator with mysql-CSDN博客
编译qt5.15.2(mac/windows)的mysql驱动(附带编译好的文件)_macos编译qt5.15.2-CSDN博客