连接QMYSQL,包含断线重连
头文件(xxx.h)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QThread.h>
#include <QQueue>
#include <QMutex>
#include <QSqlDatabase>
#include <QSqlTableModel>
#include <QSqlError>
#include <QSqlQuery>
#include <QDateTime>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QSqlRecord>
#include <QSettings>
#include <QException>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEtypedef enum DBFlag
{DBALL = 0,DBMYSQL = 1,DBMONGODB = 2,
}EDBFLAG;typedef enum ConnStatus
{INIT = 0,CONNECTED = 1,DISCONNECTED = 2
}EConnStatus;typedef void (*ThreadFunc)(void *); // 线程回调函数指针定义,threadFunc 类型是 void (*)(void *),表示要static类型函数,而非静态成员函数会隐式地接受一个 this 指针,因此非静态的实际签名是 void (CThread::*)(void *)class CThread : public QThread
{
public:CThread (QObject *parent = nullptr);~CThread ();bool Start (ThreadFunc pFunc, void *pParam);
protected:virtual void run ();
private:void *m_pThreadParm;ThreadFunc m_pFunc;QMutex m_Mutex;
};class /*XWHCOMMON_EXPORT*/ CReturn
{
public:bool m_bReturn; // 执行结果返回值,取值范围必须是枚举eCReturnCodeint m_nErrorCode; // 故障代码,取值由函数自定义QString m_sErrMsg = ""; //m_nReturn的异常详细描述CReturn();explicit CReturn(bool bReturn, int nErrorCode = 0, QString sMsg="");~CReturn();CReturn& operator = (const CReturn& ReturnObj){if (this != &ReturnObj) // longl.jiao 增减是否是自己给自己赋值的判断{m_bReturn = ReturnObj.m_bReturn;m_sErrMsg = ReturnObj.m_sErrMsg;m_nErrorCode = ReturnObj.m_nErrorCode;}else;return *this;}
};
Q_DECLARE_METATYPE(CReturn)//
//定义XwhDbClient 的错误码
//
enum class DBCLIENT_ERROR_CODE : int
{DBCLIENT = 300,OPEN_MYSQL_CLIENT_ERROR, //打开数据库客户端出错SQL_IS_EMPTY,//sql语句为空STRSQL_SIZE_OUTRANGE,//集合strsql的大小越界PARAM_EMPTY,
};#define DB_OBJ CDbClient::GetInstance()
class /*CDbClient_EXPORT*/ CDbClient : public QThread
{Q_OBJECTpublic://// 功能: 单实例通过此接口,获取数据交交互对象// 返回: 返回引用,避免用指针// 调用方法:// 主要思路://static CDbClient& GetInstance();//// 功能: 一键导出数据库中表的数据(csv格式)// 返回:// 调用方法:// 主要思路://bool saveToCsv(const QString& sSql, QList<QMap<QString, QVariant>>& result);//// 功能: 调用其他函数前,先调用此函数,它将连接数据库,准备好交互线程// 返回:// 调用方法:// 主要思路:CReturn Init();//// 功能: 停止数据库线程,并释放数据库连接对象,对应Init函数// 返回:// 调用方法:// 主要思路:CReturn UnInit();//// 功能: (同步接口)对MySql执行Select语句// 参数: sSql一次只能执行一条查询语句;result为List,一个元素为关系表的一行记录,// 一行记录又以Map的形式存储,Key为关系表的列名,Value为对应的值// 调用方法:// 主要思路:CReturn QueryMySql(const QString sSql, QList< QMap<QString, QVariant> >& result);//// 功能: (同步接口)对MySql执行增、删、改语句,此数据比较危险,请慎用// 参数:// 调用方法:// 主要思路:CReturn ExecMySql(const QString sSql);//// 功能: (同步接口)批量对MySql执行增、删、改语句// 参数:// 调用方法:lStrSql size必须小于等于100,否则会报错.// 主要思路:批量插入sqlCReturn ExecMySql(const QList<QString>& lStrSql);//// 功能: (同步接口)批量对MySql执行增、删、改语句// 参数:// 调用方法:// 主要思路:批量插入sqlCReturn ExecMySql(const QString sSql, const QMap<QString, QVariant>& mParam);//// 功能: 先执行增删除,再查询// 参数:// 调用方法:// 主要思路:CReturn ExecAndQueryMySql(const QString sExeSql, const QString sQuerySql, QList< QMap<QString, QVariant> >& result);//// 功能: mysql连接状态// 参数:// 调用方法:// 主要思路:EConnStatus GetMysqlConnStatus();//// 功能: 获取数据库所有表名称// 参数:// 调用方法:// 主要思路:CReturn GetAllTableName(QVector<QString>& vec_TableName);//// 功能: 开始事务操作// 参数:// 调用方法:// 主要思路:CReturn BeganTransaction();//// 功能: 提交// 参数:// 调用方法:// 主要思路:CReturn CommitTransaction();//// 功能: 回滚// 参数:// 调用方法:// 主要思路:CReturn RollbackTransaction();CReturn NoTransactionExec(const QString& sSql);CReturn NoTransactionExecSql(const QString& strSql, bool& execOk);//// 功能: 保存线程// 参数:// 调用方法:// 主要思路:///static void ThreadFunc_SaveFunction(void* pParam);CReturn UpdateAttribute(QString, QString);CReturn _InitValue();CReturn GetIntValue(const QString& sCategory, const QString& sKey, int& nValue);private:CDbClient(QObject* parent = nullptr);~CDbClient();//// 功能: 初始化mysql// 参数:// 返回:// 调用方法:// 主要思路:建立mysql连接CReturn InitMysql(bool breconnect = false);//// 功能: 初始化mysql// 参数:// 返回:// 调用方法:// 主要思路:建立MongoDB连接//CReturn InitMongoDB(bool breconnect = false);//// 功能: 停止mysql连接// 参数:// 返回:// 调用方法:// 主要思路:停止mysql连接void UnInitMysql();//// 功能: 停止MongoDB连接// 参数:// 返回:// 调用方法:// 主要思路:停止MongoDB连接//void UnInitMongoDB();//// 功能: MySql交互线程实体函数,从队列中提取、并执行任务(对数据库进行增、删、改查工作)// 参数:// 返回:// 调用方法:// 主要思路:里面死循环,调用ReleaseRes退出void MysqlRun();//断线重连//// 功能: MongoDb交互线程实体函数,从队列中提取、并执行任务(对数据库进行增、删、改查工作)// 参数:// 返回:// 调用方法:// 主要思路:里面死循环,调用ReleaseRes退出//void MongoDBRun();//// 功能: mysql心跳// 参数:// 返回:// 调用方法:// 主要思路:发送查询CReturn MysqlHeatBeat();//// 功能: MongoDB 心跳// 参数:// 返回:// 调用方法:// 主要思路:发送命令//CReturn MongoDBHeatBeat();//// 功能: 当alams_process表数据达到10万条时,以csv方式保存并清空表// 参数:// 返回:// 调用方法:// 主要思路:void exportToCsv(const QString& tableName, const QString& outputCsv);//// 功能: (同步接口)对MySql执行Select语句// 参数: sSql一次只能执行一条查询语句;result为List,一个元素为关系表的一行记录,// 一行记录又以Map的形式存储,Key为关系表的列名,Value为对应的值// 调用方法:// 主要思路:bool QueryMySqlIn(const QString& sSql, QList< QMap<QString, QVariant> >& result, QString& sNativeErrCode, QString& sErrMsg);//// 功能: (同步接口)对MySql执行增、删、改语句,此数据比较危险,请慎用// 参数:// 调用方法:// 主要思路:bool ExecMySqlIn(const QString& sSql, QString& sNativeErrCode, QString& sErrMsg);//// 功能: (同步接口)批量对MySql执行增、删、改语句// 参数:// 调用方法:lStrSql size必须小于等于100,否则会报错.// 主要思路:批量插入sqlbool ExecMySqlIn(const QList<QString>& lStrSql, QString& sNativeErrCode, QString& sErrMsg);///// 功能: 将对位前后相机的参数保存到数据库// 参数:// 调用方法:// 主要思路:l//void saveResultToDB(AlgMS_param param1, AlgMS_result result1);//// 功能: (同步接口)批量对MySql执行增、删、改语句// 参数:// 调用方法:// 主要思路:批量插入sqlbool ExecMySqlIn(const QString& sSql, const QMap<QString, QVariant>& mParam, QString& sNativeErrCode, QString& sErrMsg);//// 功能: 先执行增删除,再查询// 参数:// 调用方法:// 主要思路:bool ExecAndQueryMySqlIn(const QString& sExeSql, const QString& sQuerySql, QList< QMap<QString, QVariant> >& result, QString& sNativeErrCode, QString& sErrMsg);//************************************************************************// 功能描述: 创建MYSQL表// 参 数: 表名// 返 回 值: true:成功 false: 失败// 主要思路:// 调用方法:// 作者时间://************************************************************************bool CreateTable(const std::wstring strTableName);//************************************************************************// 功能描述: 执行MYSQL语句// 参 数: MYSQL语句// 返 回 值: true:成功 false: 失败// 主要思路:// 调用方法:// 作者时间://************************************************************************bool ExecSql(const QString& strSql);//************************************************************************// 功能描述: 创建MYSQL产能表// 参 数:// 返 回 值: true:成功 false: 失败// 主要思路:// 调用方法:// 作者时间://************************************************************************bool CreateCapacityTable();//************************************************************************// 功能描述: 获取数据库中所有表名// 参 数: 表名// 返 回 值: true:成功 false: 失败// 主要思路:// 调用方法:// 作者时间://************************************************************************bool QueryAllTableFromSQlite(std::vector<std::wstring>& vcTableName);//************************************************************************// 功能描述: 执行MYSQL语句,并返回需要的值// 参 数: MYSQL语句// 返 回 值: QSqlQuery// 主要思路:// 调用方法:// 作者时间://************************************************************************QSqlQuery Query(const QString& strSql);public:static void ThreadFunc_MySql(void* pParam);//static void ThreadFunc_MongoDb(void* pParam);private://QQueue< XwhDbTaskParam > m_QueueMysqlTask; //任务队列//QMutex m_QueueMysqlMutex; //任务队列的互斥量,保护queueTask队列QSqlDatabase m_MysqlClient; //数据库连接对象QMutex m_MysqlMutex; //m_DB互斥量,保护m_DB访问权限CThread m_MysqlThread; //mysql线程断线连接线程对象bool m_bMysqlRunning; //标志断线重连线程运行状态,true为运行中,false为未运行,第一次初始化连接后就需设置true,在不用连接数据库后设置为falseQMutex m_InitAndUnInitMutex; //初始化和反初始化锁,保证初始化操作和反初始化操作只能存在一次线程在执行EConnStatus m_nMysqlConnStatus; //mysql连接状态QMap<QString, QString> m_mapConfig; // 配置信息int m_nDataStatu; // 标志从数据库、配置文件加载数据的状态,0:初始状态,1:正在下载数据, 2:完成下载, 3:下载错误};class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
源文件(xxx.cpp)
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);CReturn res = DB_OBJ.Init();res = DB_OBJ._InitValue();
}MainWindow::~MainWindow()
{delete ui;
}CDbClient &CDbClient::GetInstance()
{static CDbClient s_Instance;return s_Instance;
}bool CDbClient::saveToCsv(const QString &sSql, QList<QMap<QString, QVariant> > &result)
{QDateTime startPrintTime = QDateTime::currentDateTime();// 获取当前时间QString timeStr = startPrintTime.toString("yyyyMMdd_HHmmss"); // 转换为字符串格式QFile file("D:/" + timeStr + ".csv");// 创建以时间命名的csv文件if (!file.open(QIODevice::WriteOnly | QIODevice::Text)){return false;}QString sNativeErrCode, sErrMsg;bool bIsOk = QueryMySqlIn(sSql, result, sNativeErrCode, sErrMsg);if (bIsOk){QTextStream out(&file);out << "id,category,primarykey,value,optional,min,max,defaultval,datatype,status,comments" << endl;for (const QMap<QString, QVariant>& itemMap : result){//写入csv文件的内容QString id = itemMap["id"].toString();QString category = itemMap["category"].toString();QString primarykey = itemMap["primarykey"].toString();QString value = itemMap["value"].toString();QString optional = itemMap["optional"].toString();QString min = itemMap["min"].toString();QString max = itemMap["max"].toString();QString defaultval = itemMap["defaultval"].toString();QString datatype = itemMap["datatype"].toString();QString status = itemMap["status"].toString();QString comments = itemMap["comments"].toString();out << id << "," << category << "," << primarykey << "," << value << "," << optional << "," << min << "," << max << "," << defaultval << "," << datatype << "," << status << "," << comments << endl;}file.close();}else{qDebug() << "查询数据失败,错误代码:" << sNativeErrCode << ",错误信息:" << sErrMsg;}return true;
}CReturn CDbClient::Init()
{CReturn ret;ret = InitMysql();if (true != ret.m_bReturn){return ret;}else;//ret = InitMongoDB();//if (true != ret.m_bReturn)//{// return ret;//}//else;return ret;
}CReturn CDbClient::UnInit()
{CReturn ret;UnInitMysql();//UnInitMongoDB();return ret;
}CReturn CDbClient::QueryMySql(const QString sSql, QList<QMap<QString, QVariant> > &result)
{if (sSql.isEmpty()){return CReturn(false, (int)DBCLIENT_ERROR_CODE::SQL_IS_EMPTY, tr("Sql is empty, please check the code"));}else;QString sNatvieCode = "";QString sErrMsg = "";bool bIsOk = QueryMySqlIn(sSql, result, sNatvieCode, sErrMsg);//重连CReturn ret;if (false == bIsOk && ("2003" == sNatvieCode || "2013" == sNatvieCode))//2003 无法连接到指定的MySQL服务器 2013在查询过程中失去了与MySQL服务器的连接{ret = InitMysql(true);}else;if (true == ret.m_bReturn){bIsOk = QueryMySqlIn(sSql, result, sNatvieCode, sErrMsg);}else;return CReturn(bIsOk, 0, sErrMsg);
}CReturn CDbClient::ExecMySql(const QString sSql)
{if (sSql.isEmpty()){return CReturn(false, (int)DBCLIENT_ERROR_CODE::SQL_IS_EMPTY, tr("sql is empty."));}else;QString sNatvieCode = "";QString sErrMsg = "";bool bIsOk = ExecMySqlIn(sSql, sNatvieCode, sErrMsg);CReturn ret;if (false == bIsOk && ("2003" == sNatvieCode || "2013" == sNatvieCode)){ret = InitMysql(true);}else;if (true == ret.m_bReturn){bIsOk = ExecMySqlIn(sSql, sNatvieCode, sErrMsg);}else;return CReturn(bIsOk, 0, sErrMsg);
}CReturn CDbClient::ExecMySql(const QList<QString> &lStrSql)
{if (lStrSql.size() > 200){return CReturn(false, (int)DBCLIENT_ERROR_CODE::STRSQL_SIZE_OUTRANGE, tr("lStrSql size greater than 200, please check."));}else;QString sNatvieCode = "";QString sErrMsg = "";bool bIsOk = ExecMySqlIn(lStrSql, sNatvieCode, sErrMsg);CReturn ret;if (false == bIsOk && ("2003" == sNatvieCode || "2013" == sNatvieCode)){ret = InitMysql(true);}else;if (true == ret.m_bReturn){bIsOk = ExecMySqlIn(lStrSql, sNatvieCode, sErrMsg);}else;return CReturn(bIsOk, 0, sErrMsg);
}CReturn CDbClient::ExecMySql(const QString sSql, const QMap<QString, QVariant> &mParam)
{if (sSql.isEmpty()){return CReturn(false, (int)DBCLIENT_ERROR_CODE::SQL_IS_EMPTY, tr("sql is empty."));}else;if (mParam.isEmpty()){return CReturn(false, (int)DBCLIENT_ERROR_CODE::PARAM_EMPTY, tr("mParam size is zero."));}else;QString sNatvieCode = "";QString sErrMsg = "";bool bIsOk = ExecMySqlIn(sSql, mParam, sNatvieCode, sErrMsg);CReturn ret;if (false == bIsOk && ("2003" == sNatvieCode || "2013" == sNatvieCode)){ret = InitMysql(true);}else;if (true == ret.m_bReturn){bIsOk = ExecMySqlIn(sSql, mParam, sNatvieCode, sErrMsg);}else;return CReturn(bIsOk, 0, sErrMsg);
}CReturn CDbClient::ExecAndQueryMySql(const QString sExeSql, const QString sQuerySql, QList<QMap<QString, QVariant> > &result)
{QString sNatvieCode = "";QString sErrMsg = "";bool bIsOk = ExecAndQueryMySqlIn(sExeSql, sQuerySql, result, sNatvieCode, sErrMsg);CReturn ret;if (false == bIsOk && ("2003" == sNatvieCode || "2013" == sNatvieCode)){ret = InitMysql(true);}else;if (true == ret.m_bReturn){bIsOk = ExecAndQueryMySqlIn(sExeSql, sQuerySql, result, sNatvieCode, sErrMsg);}else;return CReturn(bIsOk, 0, sErrMsg);
}EConnStatus CDbClient::GetMysqlConnStatus()
{return m_nMysqlConnStatus;
}CReturn CDbClient::GetAllTableName(QVector<QString> &sVecTableName)
{QMutexLocker locker(&m_MysqlMutex);QSqlQuery query(m_MysqlClient);QString sExecSql = QString("select table_name from information_schema.tables where table_schema = 'xwh_newdb' AND table_type = 'BASE TABLE';");query.exec(sExecSql);while (query.next()){sVecTableName.push_back(query.value(0).toString());}QString sErrMsg = query.lastError().text();return CReturn(true, 0, sErrMsg);
}CReturn CDbClient::BeganTransaction()
{QMutexLocker locker(&m_MysqlMutex);if (m_MysqlClient.transaction()){return CReturn(true);}else;return CReturn(false);
}CReturn CDbClient::CommitTransaction()
{QMutexLocker locker(&m_MysqlMutex);if (m_MysqlClient.commit()){return CReturn(true);}else;return CReturn(false);
}CReturn CDbClient::RollbackTransaction()
{QMutexLocker locker(&m_MysqlMutex);if (m_MysqlClient.rollback()){return CReturn(true);}else;return CReturn(false);
}CReturn CDbClient::NoTransactionExec(const QString &sSql)
{QMutexLocker locker(&m_MysqlMutex);bool result = false;NoTransactionExecSql(sSql, result);if (!result){RollbackTransaction();return CReturn(false);}else;return CReturn(true);
}CReturn CDbClient::NoTransactionExecSql(const QString &sSql, bool &bExecOk)
{QMutexLocker locker(&m_MysqlMutex);CReturn retValue = ExecMySql(sSql);if (retValue.m_bReturn){bExecOk = true;}else{bExecOk = false;}return retValue;
}void CDbClient::ThreadFunc_SaveFunction(void *pParam)
{//无
}CReturn CDbClient::UpdateAttribute(QString UvAttribute, QString key)
{CReturn ReturnValue(true);do{QMutexLocker locker(&m_MysqlMutex);QSqlQuery query(m_MysqlClient);QString sql = QString("UPDATE datacachecenter SET value = :value where primarykey = :key");if (query.prepare(sql)){query.bindValue(":value", UvAttribute);query.bindValue(":key",key);if (!query.exec()){ReturnValue.m_sErrMsg = query.lastError().text();ReturnValue.m_bReturn = false;break;}else;}else{ReturnValue.m_sErrMsg = QString("Fail to sql Prepare");ReturnValue.m_bReturn = false;}} while (0);return ReturnValue;
}CDbClient::CDbClient(QObject *parent):QThread(parent), m_bMysqlRunning(false)
{qRegisterMetaType< QList< QMap<QString, QVariant> > >("QList< QMap<QString, QVariant> >");qRegisterMetaType< CReturn >("CReturn ");//m_MongoDBClient = NULL; //MongoDB数据库连接对象m_nMysqlConnStatus = EConnStatus::INIT;
}CDbClient::~CDbClient()
{UnInit();
}bool FileIsExist(const QString& sFile)
{QFile tempFile(sFile);return tempFile.exists();
}CReturn GetIniFileValue(const QString& sPath, const QString& sKey, const QVariant& defaultValue, QVariant& GetValue)
{CReturn xwhReturn(true);do{if (!FileIsExist(sPath)){xwhReturn = CReturn(false, 0, QString(QObject::tr("Failed to get Ini file[%1] key[%2], Error:File not exist")).arg(sPath).arg(sKey));break;}else;try{QSettings IniObj(sPath, QSettings::Format::IniFormat);GetValue = IniObj.value(sKey, defaultValue);}catch (QException e){xwhReturn = CReturn(false, 0, QString(QObject::tr("Failed to get Ini file[%1] key[%2], Error:[%3]")).arg(sPath).arg(sKey).arg(e.what()));}} while (0);return xwhReturn;
}QString GetXOREncryptUncrypt(QString sStr)
{QByteArray text = sStr.toLocal8Bit();QByteArray by = text.fromBase64(text);QString sRe = QString::fromLocal8Bit(by); // 注意:这里是处理中文用的return sRe;
}CReturn CDbClient::InitMysql(bool breconnect)
{CReturn Return;QMutexLocker locker(&m_MysqlMutex);do{if (true == m_bMysqlRunning && false == breconnect){Return = CReturn(false, -1, tr("Mysql have be Inited , before do this, you must call the UnInit first"));break;}else;//从配置文件获取数据库登录信息QVariant GetValue;QString sIP, sUser, sPW, sDB;int nPort = 0;
# if 0Return = GetIniFileValue("../config.ini", "MySqlDB", "", GetValue);if (Return.m_bReturn != true){break;}else;sDB = GetValue.toString();Return = GetIniFileValue("../config.ini", "MySqlIP", "", GetValue);if (Return.m_bReturn != true){break;}else;sIP = GetValue.toString();Return = GetIniFileValue("../config.ini", "MySqlPORT", "", GetValue);if (Return.m_bReturn != true){break;}else;nPort = GetValue.toInt();Return = GetIniFileValue("../config.ini", "MySqlUserName", "", GetValue);if (Return.m_bReturn != true){break;}else;sUser = GetValue.toString();Return = GetIniFileValue("../config.ini", "MySqlPW", "", GetValue);if (Return.m_bReturn != true){break;}else;sPW = GetValue.toString();//sPW = GetXOREncryptUncrypt(sPW); //调试暂时屏蔽密码加密//重连关闭if (true == breconnect){m_MysqlClient.close();}else;
#endifm_MysqlClient = QSqlDatabase::addDatabase("QMYSQL");m_MysqlClient.setDatabaseName(/*sDB*/"dier_newdata");m_MysqlClient.setHostName(/*sIP*/"127.0.0.1");m_MysqlClient.setPort(/*nPort*/3306);m_MysqlClient.setUserName(/*sUser*/"root");m_MysqlClient.setPassword(/*sPW*/"");if (!m_MysqlClient.open()){//M 写日志 qDebug() << "sqlError" << m_MysqlClient.lastError();Return.m_bReturn = false;Return.m_nErrorCode = 0;Return.m_sErrMsg = m_MysqlClient.lastError().text();m_nMysqlConnStatus = EConnStatus::DISCONNECTED;break;}else{Return.m_bReturn = true;Return.m_sErrMsg = "";Return.m_nErrorCode = -4; //??m_nMysqlConnStatus = EConnStatus::CONNECTED;}//重连时不重复开启线程,第一次初始化连接数据库的时候执行设置false,然后不用连接数据库时也应设falseif (false == breconnect){m_bMysqlRunning = true;m_MysqlThread.Start(ThreadFunc_MySql, this);}else;} while (0);return Return;
}void CDbClient::UnInitMysql()
{m_bMysqlRunning = false;if (m_MysqlThread.isRunning()){//QThread::msleep(10);m_MysqlThread.quit();m_MysqlThread.wait();}else;m_MysqlClient.close();
}void CDbClient::MysqlRun()
{CReturn ret;int nHBTime = 30;int nCnt = 30;while (m_bMysqlRunning)//{if (nCnt++ < 30){QThread::sleep(1);//休眠1秒,确保能够及时退出线程continue;}else;//每个30秒发送一个心跳,保证连接不会超时nCnt = 0;ret = MysqlHeatBeat();if (true != ret.m_bReturn){ret = InitMysql(true);if (true != ret.m_bReturn){m_nMysqlConnStatus = EConnStatus::DISCONNECTED;//qDebug() << "mysql disconnet,err_msg:" << ret.m_sErrMsg;if (300 < nHBTime) {nHBTime *= 2;}else;}else;}else{m_nMysqlConnStatus = EConnStatus::CONNECTED;//qDebug() << "mysql reconnet succ.";nHBTime = 30;}}
}CReturn CDbClient::MysqlHeatBeat()
{QString sSql = "SELECT VERSION();";QList< QMap<QString, QVariant> > lResult;QMutexLocker locker(&m_MysqlMutex);QSqlQuery query(m_MysqlClient);bool bIsOk = false;try{bIsOk = query.exec(sSql);while (query.next()){QMap<QString, QVariant> itemMap;QSqlRecord record = query.record();for (int index = 0; index < record.count(); index++){itemMap[record.fieldName(index)] = record.value(index);}lResult.push_back(itemMap);}// while (query.next())// {// int id = query.value(0).toInt();// QString username = query.value(1).toString();// QString password = query.value(2).toString();// qDebug() << "ID:" << id << "Username:" << username << "Password:" << password;// }}catch (...){bIsOk = false;}return CReturn(bIsOk, 0, query.lastError().text());
}void CDbClient::exportToCsv(const QString &tableName, const QString &outputCsv)
{}bool CDbClient::QueryMySqlIn(const QString &sSql, QList<QMap<QString, QVariant> > &result, QString &sNativeErrCode, QString &sErrMsg)
{bool bIsOk = false;QMutexLocker locker(&m_MysqlMutex);QSqlQuery query(m_MysqlClient);try{bIsOk = query.exec(sSql);while (query.next()){QMap<QString, QVariant> itemMap;QSqlRecord record = query.record();for (int index = 0; index < record.count(); index++){itemMap[record.fieldName(index)] = record.value(index);}result.push_back(itemMap);}}catch (...){bIsOk = false;}sNativeErrCode = query.lastError().nativeErrorCode();sErrMsg = query.lastError().text();return bIsOk;
}bool CDbClient::ExecMySqlIn(const QString &sSql, QString &sNativeErrCode, QString &sErrMsg)
{QMutexLocker locker(&m_MysqlMutex);QSqlQuery query(m_MysqlClient);bool bIsOk = false;try{bIsOk = query.exec(sSql);}catch (...){bIsOk = false;}sNativeErrCode = query.lastError().nativeErrorCode();sErrMsg = query.lastError().text();return bIsOk;
}bool CDbClient::ExecMySqlIn(const QList<QString> &lStrSql, QString &sNativeErrCode, QString &sErrMsg)
{QMutexLocker locker(&m_MysqlMutex);QSqlQuery query(m_MysqlClient);bool bIsOk = m_MysqlClient.transaction();if (!bIsOk){sNativeErrCode = m_MysqlClient.lastError().nativeErrorCode();sErrMsg = m_MysqlClient.lastError().text();return bIsOk;}else;try{for (int i = 0; i < lStrSql.size(); ++i){QString sSql = lStrSql.at(i);bIsOk = query.exec(sSql);if (false == bIsOk){break;}else;}}catch (...){bIsOk = false;}if (bIsOk){m_MysqlClient.commit();}else{m_MysqlClient.rollback();sNativeErrCode = m_MysqlClient.lastError().nativeErrorCode();sErrMsg = m_MysqlClient.lastError().text();}return bIsOk;
}bool CDbClient::ExecMySqlIn(const QString &sSql, const QMap<QString, QVariant> &mParam, QString &sNativeErrCode, QString &sErrMsg)
{QMutexLocker locker(&m_MysqlMutex);QSqlQuery query(m_MysqlClient);bool bIsOk = false;do {try{bIsOk = query.prepare(sSql);if (false == bIsOk){break;}else;//参数绑定for (QMap<QString, QVariant>::const_iterator it = mParam.begin(); it != mParam.end(); it++){query.bindValue(it.key(), it.value()); //QDX 转换被作为参数的换位value;}bIsOk = query.exec();}catch (...){bIsOk = false;}} while (0);sNativeErrCode = query.lastError().nativeErrorCode();sErrMsg = query.lastError().text();return bIsOk;
}bool CDbClient::ExecAndQueryMySqlIn(const QString &sExeSql, const QString &sQuerySql, QList<QMap<QString, QVariant> > &result, QString &sNativeErrCode, QString &sErrMsg)
{QMutexLocker locker(&m_MysqlMutex);QSqlQuery query(m_MysqlClient);bool bIsOk = false;do {bIsOk = m_MysqlClient.transaction();if (false == bIsOk){break;}else;bIsOk = query.exec(sExeSql);if (false == bIsOk){m_MysqlClient.rollback();break;}else;bIsOk = query.exec(sQuerySql);if (false == bIsOk){m_MysqlClient.rollback();break;}else;while (query.next()){QMap<QString, QVariant> itemMap;QSqlRecord record = query.record();for (int index = 0; index < record.count(); index++){itemMap[record.fieldName(index)] = record.value(index);}result.push_back(itemMap);}m_MysqlClient.commit();} while (0);sNativeErrCode = query.lastError().nativeErrorCode();sErrMsg = query.lastError().text();return bIsOk;
}#define CAPACITYTABLE L"capacitytable"
bool CDbClient::CreateTable(const std::wstring strTableName)
{bool bRet = true;QString strExecSql = "";if (strTableName.compare(CAPACITYTABLE) == 0){strExecSql = QString("CREATE TABLE %1(Id INT AUTO_INCREMENT PRIMARY KEY,\Date DATE,\Entry_plate_time TIME,\Out_plate_time TIME,\Board_in_to_board_out_time DOUBLE,\Counterpoint_time DOUBLE,\Printing_time DOUBLE,\Platform_number TEXT,\Work_order_ID DOUBLE,\Employee_ID DOUBLE,\Production_part_number TEXT,\Plate_thickness DOUBLE,\WorkPlatformA_or_WorkPlatformB TEXT,\UV1_pass1 DOUBLE,\UV1_pass2 DOUBLE,\UV1_pass3 DOUBLE,\UV1_pass4 DOUBLE,\UV2_pass1 DOUBLE,\UV2_pass2 DOUBLE,\UV2_pass3 DOUBLE,\UV2_pass4 DOUBLE,\UV3_pass1 DOUBLE,\UV3_pass2 DOUBLE,\UV3_pass3 DOUBLE,\UV3_pass4 DOUBLE,\UV4_pass1 DOUBLE,\UV4_pass2 DOUBLE,\UV4_pass3 DOUBLE,\UV4_pass4 DOUBLE,\UV5_pass1 DOUBLE,\UV5_pass2 DOUBLE,\UV5_pass3 DOUBLE,\UV5_pass4 DOUBLE,\Print_resolution DOUBLE,\PlatformA_Print_origin TEXT,\PlatformB_Print_origin TEXT,\Head1_temperature DOUBLE,\Head2_temperature DOUBLE,\Head3_temperature DOUBLE,\Head4_temperature DOUBLE,\Head5_temperature DOUBLE,\Head6_temperature DOUBLE,\Head7_temperature DOUBLE,\Head8_temperature DOUBLE,\Head9_temperature DOUBLE,\Head10_temperature DOUBLE,\Head11_temperature DOUBLE,\Head12_temperature DOUBLE,\Head13_temperature DOUBLE,\Head14_temperature DOUBLE,\Head15_temperature DOUBLE,\Head16_temperature DOUBLE,\Head17_temperature DOUBLE,\Head18_temperature DOUBLE,\Production_plate_size DOUBLE,\Gross_area DOUBLE,\Production_quantity DOUBLE,\Total_capacity DOUBLE,\Total_production_time DOUBLE);").arg(QString::fromUtf16((const ushort*)strTableName.c_str()));}else;bRet = ExecSql(strExecSql);return bRet;
}bool CDbClient::ExecSql(const QString &strSql)
{QMutexLocker locker(&m_MysqlMutex);bool bACID = m_MysqlClient.transaction();QSqlQuery query(m_MysqlClient);if (bACID){if (query.exec(strSql)){return m_MysqlClient.commit();}else{//LOGWARNNINGCOM(L"ExecSql failed, sql: %s, error: %s.", (const wchar_t*)(strSql.utf16()), (const wchar_t*)(m_MysqlClient.lastError().databaseText().utf16()));//LOGWARNNINGCOM(L"ExecSql failed, sql: %s, error: %s.", (const wchar_t*)(strSql.utf16()), (const wchar_t*)(query.lastError().text().utf16()));return m_MysqlClient.rollback();}}return query.exec(strSql);
}void CDbClient::ThreadFunc_MySql(void *pParam)
{if (NULL == pParam)return;else;CDbClient* pThis = (CDbClient*)pParam;pThis->MysqlRun();
}CReturn::CReturn()
{m_bReturn = false; // 默认是异常,正常情况必须自行赋值m_sErrMsg = "";m_nErrorCode = 0;
}CReturn::CReturn(bool bReturn, int nErrorCode, QString sMsg)
{m_bReturn = bReturn;m_nErrorCode = nErrorCode;m_sErrMsg = sMsg;
}CReturn::~CReturn()
{}CThread::CThread(QObject *parent): QThread (parent)
{m_pFunc = nullptr;m_pThreadParm = nullptr;
}CThread::~CThread ()
{this->deleteLater();this->wait();
}void CThread::run ()
{if (nullptr != m_pFunc){m_pFunc (m_pThreadParm);}
}bool CThread::Start (ThreadFunc pFunc, void *pParam)
{QMutexLocker lock(&m_Mutex);bool bRet = false;if (!this->isRunning () && NULL != pFunc){m_pFunc = pFunc;m_pThreadParm = pParam;this->start();bRet = true;}else{// 这个线程还没有结束,不能重新启动bRet = false;}return bRet;
}// 初始化数据中心参数值
CReturn CDbClient::_InitValue()
{CReturn retValue(true);do{QString sSql = "select category,primarykey,value from datacachecenter";QList< QMap<QString, QVariant> > lstResult;retValue = DB_OBJ.QueryMySql(sSql, lstResult);if (true == retValue.m_bReturn){//获取数据库成功for (int i = 0; i < lstResult.size(); i++){const QMap<QString, QVariant>& mapOneData = lstResult.at(i);if (mapOneData["category"].toString().isEmpty() || mapOneData["primarykey"].toString().isEmpty()){//如果类别或者键值为空,则跳过continue;}else;m_mapConfig[mapOneData["category"].toString() + "." + mapOneData["primarykey"].toString()] = mapOneData["value"].toString();}}else{//获取数据库失败retValue.m_bReturn = false;retValue.m_sErrMsg = QObject::tr("Init DbClient datacachecenter value error:") + retValue.m_sErrMsg;break;}} while (0);return retValue;
}CReturn CDbClient::GetIntValue(const QString& sCategory, const QString& sKey, int& nValue)
{CReturn retValue(true);if (sCategory.trimmed().isEmpty() || sKey.trimmed().isEmpty()){//若输入的类别和键为空,直接返回retValue.m_bReturn = false;retValue.m_sErrMsg = QObject::tr("The category or key is empty.,please packaged logs and send developer.");//LOGERROR(retValue.m_sErrMsg);return retValue;}else;int nTimes = 0;do{while (m_nDataStatu != 2 && nTimes < 5000){nTimes += 500;QThread::msleep(500);}if (nTimes >= 5000){retValue.m_bReturn = false;retValue.m_sErrMsg = QObject::tr("GetValue about sKey(%1) timeout,please packaged logs and send developer.").arg(sKey);//LOGERROR(retValue.m_sErrMsg);break;}else;QString strValue = m_mapConfig[sCategory + "." + sKey];nValue = strValue.toInt();} while (0);return retValue;
}