1.前言
上次搭建好環境後,想單獨的開發出各個模塊。首先的是數據庫模塊,後續還有XML文件,excel讀寫,插件間信號傳遞,線程池,數據加密等模塊。把各個模塊集成成一個差價,後面如果想寫什麼東西,直接就可以拿來調用。
2.內容
數據庫模塊,考慮到實際項目中遇到的情況,採用單例模式設計數據庫插件類DBservice。外面包裝一層接口DBserviceCtrl類,只給其他插件調用的接口。
具體實現如下:DBservice.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "head.h"
#include <QSqlDatabase>
#include <QMessageBox>
#include <QSqlQuery>
#include <QSqlError>
#include <QList>
#include <string>
#include <QMutex>
#include <QVariant>
namespace DBService
{
// 定義MySQL連接信息
typedef struct
{
QString server;
QString user;
QString password;
QString database;
int port;
}MySQLConInfo;
enum SQL_ERROR
{
IUIT_FAIL,
IUIT_SUCCES
};
typedef struct
{
SQL_ERROR Error_Info;
QSqlError Error_Code;
}ErrorInfo;
//餓漢式單例模式
class BIL_SHARE DbService : public QObject
{
Q_OBJECT
public:
//連接數據庫
bool createConnection();
// 讀取數據,返回數量
int DBSelect(const std::string& Querystr, QList<QString>& data);
// 更新數據,返回數量
int DBUpdate(const std::string& Querystr, QList<QString> & datafamt, QList<QString> & data);
//插入數據,返回數量
int DBInsert(const std::string& Querystr, QList<QString> & datafamt, QList<QString>& data);
//刪除數據,返回數量
int DBDelete(const std::string& Querystr, QList<QString> & data);
// 其他操作
int Query(const std::string& Querystr);
bool DBCreateTable(QList<QString> tableList);
//獲取返回信息,錯誤碼等
void GetDBErrorInfo(ErrorInfo& errorInfo);
// 插入並獲取插入的ID,針對自動遞增ID
int GetInsertID(const std::string& Querystr);
public:
static DbService* Instance();
//類似Java的垃圾回收器
class GC
{
public:
~GC()
{
//釋放連接和資源
if (m_dbService != NULL)
{
delete m_dbService;
m_dbService = NULL;
//關閉數據庫
db.close();
}
}
static GC gc; // 用於釋放單例
};
private:
DbService();
DbService(const DbService &);
//DBservice& operator=(const DBservice &);
private:
static DbService *m_dbService;
static QSqlDatabase db; //數據庫連接類
static QMutex m_mutex; // 鎖
private:
MySQLConInfo m_mySqlConInfo; //數據庫連接信息
ErrorInfo m_ErrorInfo; //錯誤信息
};
}
DBservice.cpp
#include "DBservice.h"
namespace DBService
{
DbService* DbService::m_dbService = NULL;
QSqlDatabase DbService::db; //數據庫連接類
QMutex DbService::m_mutex; // 鎖
QMutex DbService::m_mutex1; // 鎖
DbService::GC DbService::GC::gc; // 重要
DbService::DbService()
{
}
DbService* DbService::Instance()
{
//保證多線程安全,加鎖
m_mutex.lock();
if (m_dbService == NULL)
{
m_mutex1.lock();
if (m_dbService == NULL)
{
m_dbService = new DbService();
}
m_mutex1.unlock();
}
m_mutex.unlock();
return m_dbService;
}
bool DbService::createConnection()
{
db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("mqtest"); //這裏輸入你的數據庫名
db.setUserName("*****");
db.setPassword("*******"); //這裏輸入你的密碼
if (!db.open()) {
QMessageBox::critical(0, QObject::tr("無法打開數據庫"), db.lastError().databaseText(), QMessageBox::Cancel);
m_ErrorInfo.Error_Code = db.lastError();
m_ErrorInfo.Error_Info = IUIT_FAIL;
return false;
} //
return true;
}
//創建表
bool DbService::DBCreateTable(QList<QString> tableList)
{
QString qslname;
for (int i = 1; i < tableList.count() - 1; i++)
qslname += (tableList.at(i) + " VARCHAR(40),");
QString sql = tr("create table %1(" "id INT NOT NULL AUTO_INCREMENT,%2PRIMARY KEY (id));").arg(tableList.at(0)).arg(qslname);
QSqlQuery query(db);
if (!query.exec(sql))
{
m_ErrorInfo.Error_Code = query.lastError();
m_ErrorInfo.Error_Info = IUIT_FAIL;
return false;
}
return true;
}
// 讀取數據,返回數量
int DbService::DBSelect(const std::string& Querystr, QList<QString>& data)
{
QString sql = tr("select * from '%1'").arg(tr("表名"));
int count = 0;
QSqlQuery query(db);
memset(&m_ErrorInfo, 0, sizeof(m_ErrorInfo));
// 使數據庫支持中文
query.exec("SET NAMES 'UTF8'");
if (!query.exec(sql))
{
m_ErrorInfo.Error_Code = query.lastError();
m_ErrorInfo.Error_Info = IUIT_FAIL;
return count;
}
while (query.next())
{
data.push_back(query.value(count++).toString());
}
return count;
}
// 更新數據,返回數量 修改列名,修改內容
int DbService::DBUpdate(const std::string& Querystr, QList<QString> & datafamt, QList<QString> & data)
{
int count = 0;
QString sqlset;
for (int i = 0; i < data.count(); i++)
sqlset += "" + datafamt.at(i) + " ='" + data.at(i) + "',";
sqlset = sqlset.left(sqlset.length() - 1);
QString sql = tr("update %1 set ").arg("id") + sqlset + tr(" where id = %1").arg(sqlset);
QSqlQuery query(db);
memset(&m_ErrorInfo, 0, sizeof(m_ErrorInfo));
// 使數據庫支持中文
query.exec("SET NAMES 'UTF8'");
if (!query.exec(sql))
{
m_ErrorInfo.Error_Code = query.lastError();
m_ErrorInfo.Error_Info = IUIT_FAIL;
return count;
}
count = query.size();
return count;
}
//插入數據,返回數量
int DbService::DBInsert(const std::string& Querystr, QList<QString> & datafamt, QList<QString> & data)
{
int count = 0;
QString sqlDataFamt,sqlData;
for (int i = 0; i < datafamt.count(); i++)
{
sqlDataFamt += "" + datafamt.at(i) + ",";
sqlData += "" + datafamt.at(i) + ",";
}
QString sql = tr("update INTO %1 (%2) VALUES (%3) ").arg("表名").arg(sqlDataFamt).arg(sqlData);
QSqlQuery query(db);
memset(&m_ErrorInfo, 0, sizeof(m_ErrorInfo));
// 使數據庫支持中文
query.exec("SET NAMES 'UTF8'");
if (!query.exec(sql))
{
m_ErrorInfo.Error_Code = query.lastError();
m_ErrorInfo.Error_Info = IUIT_FAIL;
return count;
}
count = query.size();
return count;
}
//刪除數據,返回數量
int DbService::DBDelete(const std::string& Querystr, QList<QString> & data)
{
int count = 0;
QSqlQuery query(db);
QString sql = QString("delete from %2 where id=%1").arg(data[0]).arg("表名");
memset(&m_ErrorInfo, 0, sizeof(m_ErrorInfo));
// 使數據庫支持中文
query.exec("SET NAMES 'UTF8'");
if (!query.exec(sql))
{
m_ErrorInfo.Error_Code = query.lastError();
m_ErrorInfo.Error_Info = IUIT_FAIL;
return count;
}
count = query.size();
return count;
}
// 其他操作
int DbService::Query(const std::string& Querystr)
{
int count = 0;
return count;
}
//獲取返回信息,錯誤碼等
void DbService::GetDBErrorInfo(ErrorInfo& errorInfo)
{
errorInfo.Error_Code = m_ErrorInfo.Error_Code;
errorInfo.Error_Info = m_ErrorInfo.Error_Info;
}
}
接口類:DBserviceCtrl.h
#pragma once
#include "DBservice.h"
#include "head.h"
namespace DBService {
//連接數據庫
bool BIL_SHARE createConnection();
// 讀取數據,返回數量
int BIL_SHARE DBSelect(const std::string& Querystr, QList<QString>& data);
// 更新數據,返回數量
int BIL_SHARE DBUpdate(const std::string& Querystr, QList<QString> & datafamt, QList<QString> & data);
//插入數據,返回數量
int BIL_SHARE DBInsert(const std::string& Querystr, QList<QString> & datafamt, QList<QString>& data);
//刪除數據,返回數量
int BIL_SHARE DBDelete(const std::string& Querystr, QList<QString> & data);
// 其他操作
int BIL_SHARE Query(const std::string& Querystr);
bool BIL_SHARE DBCreateTable(QList<QString> tableList);
//獲取返回信息,錯誤碼等
void BIL_SHARE GetDBErrorInfo(ErrorInfo& errorInfo);
// 插入並獲取插入的ID,針對自動遞增ID
//int GetInsertID(const std::string& Querystr);
}
#include "DBserviceCtrl.h"
namespace DBService {
//連接數據庫
bool createConnection()
{
return DBService::DbService::Instance()->createConnection();
}
// 讀取數據,返回數量
int DBSelect(const std::string& Querystr, QList<QString>& data)
{
return DBService::DbService::Instance()->DBSelect(Querystr, data);
}
// 更新數據,返回數量
int DBUpdate(const std::string& Querystr, QList<QString> & datafamt, QList<QString> & data)
{
return DBService::DbService::Instance()->DBUpdate(Querystr, datafamt, data);
}
//插入數據,返回數量
int DBInsert(const std::string& Querystr, QList<QString> & datafamt, QList<QString>& data)
{
return DBService::DbService::Instance()->DBInsert(Querystr, datafamt, data);
}
//刪除數據,返回數量
int DBDelete(const std::string& Querystr, QList<QString> & data)
{
return DBService::DbService::Instance()->DBDelete(Querystr, data);
}
// 其他操作
int Query(const std::string& Querystr)
{
return DBService::DbService::Instance()->Query(Querystr);
}
bool DBCreateTable(QList<QString> tableList)
{
return DBService::DbService::Instance()->DBCreateTable(tableList);
}
//獲取返回信息,錯誤碼等
void GetDBErrorInfo(ErrorInfo& errorInfo)
{
DBService::DbService::Instance()->GetDBErrorInfo(errorInfo);
}
// 插入並獲取插入的ID,針對自動遞增ID
//int DBserviceCtrl::GetInsertID(const std::string& Querystr)
//{
// return m_dbService->GetInsertID(Querystr);
//}
}
3.遇到的問題
1.非常低級的錯誤,靜態變量未初始化。。。
2.沒有將該插件設置爲生成.dll文件,生成後事件未添加,包含目錄等信息未添加。所以在別的插件中調用時,一直報找不到的錯誤。
3.嚴重性 代碼 說明 項目 文件 行 禁止顯示狀態
錯誤 LNK2001 無法解析的外部符號 "public: static struct QMetaObject const DBService::DbService::staticMetaObject" (?staticMetaObject@DbService@DBService@@2UQMetaObject@@B) First E:\QT5.9\First\First\First.obj 1
錯誤原因是,找不到moc*****.cpp文件。在網上找了很多,都說是怎麼生成moc文件等等,當時moc文件是已經生成的,所以我以爲是路徑的問題,在屬性設置下,C/C++,鏈接器下都添加了對應路徑。都沒有用。。。
解決辦法:無意間,將生成的數據類這邊的moc文件複製到調用插件的生成moc文件的路徑下,就編譯通過 啦