無經驗做網站今日軍事新聞最新消息新聞
本文將詳細介紹如何在Qt應用程序中集成MySQL數據庫,并封裝實現好用的mysql數據庫操作類。包括環(huán)境準備、連接數據庫、執(zhí)行查詢及異常處理等關鍵步驟,同時包含mysql驅動的編譯。分享給有需要的小伙伴,喜歡的可以點擊收藏。
目錄
環(huán)境準備
項目配置
簡單使用
?簡單示例
模塊類封裝
?如何使用
附qsqlmysql庫的構建
前提條件
構建步驟
1. 查找Qt的安裝路徑和編譯器
2. 設置環(huán)境變量
3. 獲取MySQL開發(fā)庫
4. 構建?qsqlmysql?插件
Windows:
Linux:
5. 將編譯好的插件拷貝到合適的位置
注意事項
其他資源
Qt提供了QtSql模塊來進行獨立于平臺的數據庫操作,這里的“平臺”既包括操作系統(tǒng)平臺,也包括各個數據庫平臺。Qt使用一個QDatabase表示一個數據庫連接。在底層,Qt使用不同的驅動程序來與不同的數據庫API進行交互。
通常Qt只默認搭載了QSqlLite驅動程序,如果需要使用其他數據庫,需要下載相應的數據庫驅動,如mysql的為?qsqlmysql.dll,同時還需要mysql的客戶端庫libmysql.dll。
在連接數據庫之前可以使用QSqlDatabase::drivers()
查看本機Qt已經支持的數據庫驅動。
環(huán)境準備
1.安裝MySQL數據庫:首先確保你的系統(tǒng)中安裝了MySQL服務器,并創(chuàng)建好數據庫和表結構。
2.安裝Qt開發(fā)環(huán)境:安裝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目錄中。如果不存在該庫,則程序執(zhí)行會報QSqlDatabase: QMYSQL driver not loaded的錯誤。
如果要構建QMYSQL,需安裝Qt源代碼,并確保你的系統(tǒng)中安裝了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動態(tài)庫。(libmysql.dll動態(tài)庫。鏈接: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;
}//執(zhí)行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;
}//執(zhí)行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);//執(zhí)行sql語句,不獲取結果bool queryExec(QString sqlStr,QList<QHash<QString,QString>> &data);//執(zhí)行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環(huán)境下,可以直接下載 MySQL C API 開發(fā)包 (MySQL Connector/C)。
- Linux環(huán)境,可通過包管理器安裝(例如?
sudo apt-get install libmysqlclient-dev
)。 - macOS環(huán)境,可通過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. 設置環(huán)境變量
- 將Qt的編譯工具(如
qmake
)添加到系統(tǒng)的PATH
變量中。
3. 獲取MySQL開發(fā)庫
- 確保你已經下載并解壓了 MySQL Connector/C 用于 Windows 系統(tǒng);在Linux和macOS系統(tǒng)上安裝相應的開發(fā)庫會自動設置好的路徑。
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 = qsqlmysqlHEADERS += $$PWD/qsql_mysql_p.h
SOURCES += $$PWD/qsql_mysql.cpp $$PWD/main.cpp#注釋到這個
#QMAKE_USE += mysqlOTHER_FILES += mysql.jsonPLUGIN_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 使用的編譯器版本一致。
- 路徑問題:在運行示例程序時,所有路徑要使用絕對路徑或將相關路徑加入到環(huán)境變量中以確保 Qt 能夠找到相應的庫文件。
- 權限問題:在Linux和macOS環(huán)境下,可能需要使用
sudo
來執(zhí)行某些命令以擁有足夠的權限。
按照上述步驟,你應該能夠成功構建并使用?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博客
QT操作Mysql數據庫_qt mysql-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博客