源码地址:https://download.csdn.net/download/wangyi463295828/86502612
框架采用生产/消费者模式+回调通知的形式,模拟数据库访问操作。在实际的生产项目中,我们访问的数据有可能来自本模块、其他插件模块、本地文件、本地数据库或者也有可能是远程数据库,这当中影响I/O访问效率的因素很多,对于网络访问,很大程度上是会受网络波动、server性能等因素的影响,在访问端,为了不影响自身业务的执行,我们可以采用异步访问的方式。等获取到数据后,再通过回调将数据抛出。
1、定义范围跟协议
包括:数据库操作类型:insert、update、delete、select;
要执行的sql语句;
执行完成后的回调函数
每一次查询都需要构建这样的消息协议。
//fetchdbdatamessage.h
#ifndef FETCHDBDATAMESSAGE_H
#define FETCHDBDATAMESSAGE_H
#include <QObject>
#include <QList>
#include <QStringList>
typedef std::function<void(QList<QStringList>)> DBCALLBACK;
class FetchDBDataMessage : public QObject
{
Q_OBJECT
public:
enum Fetch_Type {
opt_insert = 0,
opt_delete,
opt_update,
opt_select
};
explicit FetchDBDataMessage(QObject *parent = nullptr);
Fetch_Type type{opt_select};
QString strSQL;
DBCALLBACK _func; //注意:注册的回调函数只用来接收sql执行结果和获取数据。不能做耗时的业务操作,更不能阻塞
};
#endif // FETCHDBDATAMESSAGE_H
#include "fetchdbdatamessage.h"
FetchDBDataMessage::FetchDBDataMessage(QObject *parent)
: QObject{parent}
{
}
2、定义业务线程
这个类主要用来在子线程中搭建生产消费者模型 ,处理业务层的数据访问请求。
//fetchdbdata.h
#ifndef FETCHDBDATA_H
#define FETCHDBDATA_H
#include <QObject>
#include <QThread>
#include "fetchdbdatamessage.h"
namespace libra {
namespace adapter{
namespace internal {
class FetchDBDataPrivate;
}
class FetchDBData : public QThread
{
Q_OBJECT
public:
explicit FetchDBData(QObject *parent = nullptr);
~FetchDBData();
void appenedSqlMessage(std::shared_ptr<FetchDBDataMessage> pMsg);
void startSQL();
void stopSQL();
signals:
protected:
void start(Priority = InheritPriority);
protected:
void run() override;
bool execSQL(std::shared_ptr<FetchDBDataMessage> pMsg);
private:
internal::FetchDBDataPrivate* _d{nullptr};
friend class internal::FetchDBDataPrivate;
};
}
}
#endif // FETCHDBDATA_H
循环等待新的sql申请,并执行sql语句,执行结果通过协议体中的回调函数返回。
//fetchdbdata.cpp
#include "fetchdbdata.h"
#include <QList>
#include <QMutex>
#include <QDebug>
#include <QWaitCondition>
using namespace libra;
using namespace libra::adapter;
namespace libra {
namespace adapter {
namespace internal {
const int MAX_WAIT_TIME = 2000;
class FetchDBDataPrivate{
public:
FetchDBDataPrivate(){}
~FetchDBDataPrivate(){}
QList<std::shared_ptr<FetchDBDataMessage>> m_sqlMessageList;
QMutex m_mtxSqlMessages;
QWaitCondition m_wcSqlMessages;
bool m_isStoped{false};
};
}
}
}
FetchDBData::FetchDBData(QObject *parent)
: QThread{parent}
, _d(new internal::FetchDBDataPrivate())
{
}
FetchDBData::~FetchDBData()
{
if(_d)
{
delete _d;
_d = nullptr;
}
}
void FetchDBData::appenedSqlMessage(std::shared_ptr<FetchDBDataMessage> pMsg)
{
QMutexLocker locker(&_d->m_mtxSqlMessages);
_d->m_sqlMessageList.push_back(pMsg);
_d->m_wcSqlMessages.wakeAll();
}
void FetchDBData::startSQL()
{
_d->m_isStoped = false;
FetchDBData::start();
}
void FetchDBData::stopSQL()
{
while (isRunning()){
QMutexLocker locker(&_d->m_mtxSqlMessages);
_d->m_isStoped = true;
_d->m_wcSqlMessages.wakeAll();
}
}
void FetchDBData::start(Priority p)
{
QThread::start(p);
}
void FetchDBData::run()
{
while(!_d->m_isStoped)
{
QList<std::shared_ptr<FetchDBDataMessage>> msgList;
QMutexLocker locker(&_d->m_mtxSqlMessages);
if(_d->m_sqlMessageList.isEmpty())
{
_d->m_wcSqlMessages.wait(&_d->m_mtxSqlMessages, internal::MAX_WAIT_TIME);
if(_d->m_sqlMessageList.isEmpty())
{
std::swap(msgList, _d->m_sqlMessageList);
_d->m_sqlMessageList.clear();
}
}
else
{
std::swap(msgList, _d->m_sqlMessageList);
_d->m_sqlMessageList.clear();
}
locker.unlock();
if(msgList.isEmpty())
{
continue;
}
while (!msgList.isEmpty()) {
std::shared_ptr<FetchDBDataMessage> pMsg = msgList.takeFirst();
if(!execSQL(pMsg))
{
qWarning() <<"execSQL Fail!";
}
}
}
}
bool FetchDBData::execSQL(std::shared_ptr<FetchDBDataMessage> pMsg)
{
QThread::msleep(1000); //模拟查数据耗时
QList<QStringList> dbDataList;
if(FetchDBDataMessage::FetchDBDataMessage::Fetch_Type::opt_select == pMsg->type)
{
//构造假数据
for(int i=0; i<10; i++)
{
QStringList data;
data<<QString("查询成功");
data<<QString("%1").arg(i);
data <<":";
data <<"data-data-data";
dbDataList.push_back(data);
}
}else if(FetchDBDataMessage::FetchDBDataMessage::Fetch_Type::opt_insert == pMsg->type){
QStringList data;
data<<QString("插入成功");
dbDataList.push_back(data);
}else if(FetchDBDataMessage::FetchDBDataMessage::Fetch_Type::opt_delete == pMsg->type){
QStringList data;
data<<QString("删除成功");
dbDataList.push_back(data);
}else if(FetchDBDataMessage::FetchDBDataMessage::Fetch_Type::opt_update == pMsg->type){
QStringList data;
data<<QString("更新成功");
dbDataList.push_back(data);
}else{
qCritical() << "unkonwn sql opt!";
return false;
}
if(!pMsg->_func)
{
qCritical() <<"_func is nullptr!";
return false;
}
//通知外层查询结果
pMsg->_func(dbDataList);
return true;
}
3、对外提供的单例类,业务代码通过构造协议消息体 FetchDBDataMessage,进行execSql调用,并在回调函数中等待执行结果。
//fetchdatamananger.h
#ifndef FETCHDATAMANANGER_H
#define FETCHDATAMANANGER_H
#include <QObject>
#include <memory>
#include "fetchdbdatamessage.h"
namespace libra {
namespace adapter {
namespace internal {
class FetchDataManangerPrivate;
}
class FetchDataMananger : public QObject
{
Q_OBJECT
public:
static FetchDataMananger* getInstnce();
static releaseInstance();
void init();
void uninit();
void execSQL(std::shared_ptr<FetchDBDataMessage> pSql);
private:
explicit FetchDataMananger(QObject *parent = nullptr);
~FetchDataMananger();
signals:
private:
internal::FetchDataManangerPrivate* _d{nullptr};
friend class internal::FetchDataManangerPrivate;
};
}
}
#endif // FETCHDATAMANANGER_H
//fetchdatamananger.cpp
#include "fetchdatamananger.h"
#include "fetchdbdata.h"
namespace libra {
namespace adapter {
namespace internal {
FetchDataMananger* pFetchDataMananger = nullptr;
class FetchDataManangerPrivate
{
public:
FetchDBData m_fetchData;
};
}
FetchDataMananger *FetchDataMananger::getInstnce()
{
static std::once_flag s_flag;
std::call_once(s_flag,
[](){internal::pFetchDataMananger = new FetchDataMananger();});
return internal::pFetchDataMananger;
}
FetchDataMananger::releaseInstance()
{
delete internal::pFetchDataMananger;
internal::pFetchDataMananger = nullptr;
}
void FetchDataMananger::init()
{
_d->m_fetchData.startSQL();
}
void FetchDataMananger::uninit()
{
_d->m_fetchData.stopSQL();
}
void FetchDataMananger::execSQL(std::shared_ptr<FetchDBDataMessage> pSql)
{
_d->m_fetchData.appenedSqlMessage(pSql);
}
FetchDataMananger::FetchDataMananger(QObject *parent)
: QObject{parent}
, _d(new internal::FetchDataManangerPrivate())
{
}
FetchDataMananger::~FetchDataMananger()
{
if(internal::pFetchDataMananger)
{
delete internal::pFetchDataMananger;
internal::pFetchDataMananger = nullptr;
}
if(_d)
{
delete _d;
_d = nullptr;
}
}
}
}
4、以下是框架的测试代码。
#ifndef A_TEST_BUSINESS_H
#define A_TEST_BUSINESS_H
#include <QObject>
namespace libra {
namespace business{
namespace internal{
class A_TEST_BusinessPrivate;
}
class A_TEST_Business : public QObject
{
Q_OBJECT
public:
explicit A_TEST_Business(QObject *parent = nullptr);
~A_TEST_Business();
//向数据库添加数据
void addDataToDb();
//从数据库删除数据
void deleteDataFromDb();
//更新数据库数据
void updataDataFromDb();
//从数据库查询数据
void selectDataFromDb();
signals:
private:
internal::A_TEST_BusinessPrivate* _d{nullptr};
friend class internal::A_TEST_BusinessPrivate;
};
}
}
#endif // A_TEST_BUSINESS_H
#include "a_test_business.h"
#include "fetchdatamananger.h"
#include <QMutex>
#include <QDebug>
namespace libra {
namespace business {
namespace internal {
class A_TEST_BusinessPrivate
{
public:
QMutex mx;
QList<QStringList> data;
};
}
A_TEST_Business::A_TEST_Business(QObject *parent)
: QObject{parent}
, _d(new internal::A_TEST_BusinessPrivate())
{
}
A_TEST_Business::~A_TEST_Business()
{
if(_d)
{
delete _d;
_d = nullptr;
}
}
void A_TEST_Business::addDataToDb()
{
std::shared_ptr<FetchDBDataMessage> pSQL(new FetchDBDataMessage());
pSQL->type = FetchDBDataMessage::Fetch_Type::opt_insert;
pSQL->strSQL = QString("INSTER");
pSQL->_func = [&](QList<QStringList> listResult){
for (int i = 0; i < listResult.size(); ++i) {
qInfo() <<listResult.at(i);
}
QMutexLocker locker(&_d->mx);
_d->data = listResult;
};
libra::adapter::FetchDataMananger::getInstnce()->execSQL(pSQL);
}
void A_TEST_Business::deleteDataFromDb()
{
std::shared_ptr<FetchDBDataMessage> pSQL(new FetchDBDataMessage());
pSQL->type = FetchDBDataMessage::Fetch_Type::opt_delete;
pSQL->strSQL = QString("delete");
pSQL->_func = [&](QList<QStringList> listResult){
for (int i = 0; i < listResult.size(); ++i) {
qInfo() <<listResult.at(i);
}
QMutexLocker locker(&_d->mx);
_d->data = listResult;
};
libra::adapter::FetchDataMananger::getInstnce()->execSQL(pSQL);
}
void A_TEST_Business::updataDataFromDb()
{
std::shared_ptr<FetchDBDataMessage> pSQL(new FetchDBDataMessage());
pSQL->type = FetchDBDataMessage::Fetch_Type::opt_update;
pSQL->strSQL = QString("delete");
pSQL->_func = [&](QList<QStringList> listResult){
for (int i = 0; i < listResult.size(); ++i) {
qInfo() <<listResult.at(i);
}
QMutexLocker locker(&_d->mx);
_d->data = listResult;
};
libra::adapter::FetchDataMananger::getInstnce()->execSQL(pSQL);
}
void A_TEST_Business::selectDataFromDb()
{
std::shared_ptr<FetchDBDataMessage> pSQL(new FetchDBDataMessage());
pSQL->type = FetchDBDataMessage::Fetch_Type::opt_select;
pSQL->strSQL = QString("SELECT * FROM t_test");
pSQL->_func = [&](QList<QStringList> listResult){
for (int i = 0; i < listResult.size(); ++i) {
qInfo() <<listResult.at(i);
}
QMutexLocker locker(&_d->mx);
_d->data = listResult;
};
libra::adapter::FetchDataMananger::getInstnce()->execSQL(pSQL);
}
}
}
循环进行数据申请。
#include <QCoreApplication>
#include <memory>
#include <QDebug>
#include <QThread>
#include <QList>
#include <QStringList>
#include "fetchdatamananger.h"
#include "a_test_business.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
libra::adapter::FetchDataMananger::getInstnce()->init();
int64_t count = 0;
while (true) {
// std::shared_ptr<FetchDBDataMessage> pSQL(new FetchDBDataMessage());
// pSQL->type = FetchDBDataMessage::Fetch_Type::opt_select;
// pSQL->strSQL = QString("SELECT * FROM t_test");
// pSQL->_func = [&](QList<QStringList> listResult){
// qInfo() <<"===================================================";
// qInfo() <<"第"<<++count<<"次查询结果";
// for (int i = 0; i < listResult.size(); ++i) {
// qDebug() << listResult.at(i);
// }
// qInfo() <<"===================================================";
// };
// libra::adapter::FetchDataMananger::getInstnce()->execSQL(pSQL);
libra::business::A_TEST_Business aTest;
aTest.addDataToDb();
aTest.deleteDataFromDb();
aTest.updataDataFromDb();
aTest.selectDataFromDb();
QThread::msleep(2000);
}
libra::adapter::FetchDataMananger::getInstnce()->uninit();
return a.exec();
}