qx::QxSqlDatabase::getSingleton()->setDatabaseName("./test_qxorm.db");
qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
qx::QxSqlDatabase::getSingleton()->setUserName("root");
qx::QxSqlDatabase::getSingleton()->setPassword("");
在每个线程中分别使用多个线程中的多个数据库。
但在实际尝试使用它时,MONGODB 实现似乎并非如此。 另外,在查看
qx::dao::call_query
的源代码时,它看起来并没有像其他 SQL 那样实现。
主要问题:我如何对 MONGODB 做同样的事情?
QXMONGODB
驱动程序时是否定义了不同的方式来执行此操作,或者在 QxOrm 中没有以任何方式实现?这是 Qt 中的一个示例,我尝试查看它。
db_interactor.h
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QJsonDocument>
#include <QObject>
#include <QxOrm.h>
class db_interactor : public QObject
{
Q_OBJECT
public:
explicit db_interactor(QObject *parent = nullptr);
db_interactor(QString configFilename, QObject *parent = nullptr);
signals:
void errorNoReturn (QString errString);
void errorReturn (QString errString);
void initComplete();
void dataReady (QJsonDocument response);
public slots:
void init();
void runQuery();
private:
bool inited = false;
QHash<QString, QString> config;
qx::QxSqlDatabase *db;
};
db_interactor.cpp
#include "db_interactor.h"
db_interactor::db_interactor(QString configFileName, QObject *parent) : QObject{parent}
{
if (!configFileName.isEmpty())
{
//....
config.insert(/*From file*/);
}
//...
}
void db_interactor::init()
{
db = qx::QxSqlDatabase::getSingleton();
qDebug () << "Database Pointer" << db;
db->setDriverName("QXMONGODB");
db->setHostName("localhost");
if (config.contains("DB"))
{
qDebug () << "Setting DB : " << config["DB"];
db->setDatabaseName(config["DB"]);
}
else
{
qDebug () << "_________CONFIG DOES NOT CONTAIN \"DB\"_________________";
db->setDatabaseName("new_db");
}
qDebug () << "____________Initialising DB____________";
qDebug () << db->getDatabase();
inited = true;
emit initComplete();
}
void db_interactor::runQuery()
{
if (inited)
{
qx_query nq ("{\"insert\" : \"some_coll\" , \"documents\" : [{\"a\" : 213}]}");
QSqlError err = qx::dao::call_query(nq);
if (err.isValid())
{
qDebug () << "Error writing to db : " << err.driverText();
emit errorReturn("Error writing to db : " + err.driverText());
}
else
{
emit errorNoReturn("Written to DB");
qx_query bq ("cursor" , "{\"find\" : \"some_coll\"}");
err = qx::dao::call_query(bq);
if (err.isValid())
{
qDebug () << "Error reading from db : " << err.driverText();
emit errorReturn("Error reading from db : " + err.driverText());
return;
}
emit dataReady
(QJsonDocument::fromJson(bq.response().toString().toUtf8()));
}
return;
}
errorReturn ("Not Initialised yet");
}
在另一个 QObject 类中创建该类的 2 个对象并将它们移动到单独的线程...
mainthingy.h
#include <QObject>
#include <QThread>
#include <QDebug>
#include <QTimer>
#include "db_interactor.h"
class mainThingy : public QObject
{
Q_OBJECT
QThread aFewThreads[2];
public:
explicit mainThingy(QObject *parent = nullptr);
// Ignore the destructor for now, as that is not the point in question
signals:
void init1 ();
void init2 ();
void runQr1 ();
void runQr2 ();
private slots:
void dataFrom1 (QJsonDocument response);
void dataFrom2 (QJsonDocument response);
void showErrReturn (QString err, int thread);
private:
db_interactor *di1, *di2;
void f_init1();
void f_init2();
void f_rq1();
void f_rq2();
void interface();
bool user_time = true;
QTimer ui_timer;
};
mainthingy.cpp
#include "mainthingy.h"
#include <iostream>
#include <string>
mainThingy::mainThingy(QObject *parent)
: QObject{parent}
{
di1 = new db_interactor(QStringLiteral(":/conf1.ini"));
di2 = new db_interactor(QStringLiteral(":/conf2.ini"));
di1->moveToThread(&aFewThreads[0]);
di2->moveToThread(&aFewThreads[1]);
aFewThreads[0].start();
aFewThreads[1].start();
connect(this, &mainThingy::init1, di1, &db_interactor::init);
connect(di1, &db_interactor::initComplete, this, [this]()
{
qDebug () << "DB Interactor 1 Init Complete";
user_time = true;
});
connect(di2, &db_interactor::initComplete, this, [this]()
{
qDebug () << "DB Interactor 2 Init Complete";
user_time = true;
});
connect(this, &mainThingy::init2, di2, &db_interactor::init);
connect(this, &mainThingy::runQr1, di1, &db_interactor::runQuery);
connect(this, &mainThingy::runQr2, di2, &db_interactor::runQuery);
connect(di1, &db_interactor::dataReady, this, &mainThingy::dataFrom1);
connect(di2, &db_interactor::dataReady, this, &mainThingy::dataFrom2);
connect(di1, &db_interactor::errorReturn, this, [this] (QString eS)
{
showErrReturn(eS, 1);
});
connect(di2, &db_interactor::errorReturn, this, [this] (QString eS)
{
showErrReturn(eS, 2);
});
interface();
connect(&ui_timer, &QTimer::timeout, this, [this] ()
{
if (this->user_time)
{
interface();
}
});
ui_timer.start(2000);
}
void mainThingy::dataFrom1(QJsonDocument response)
{
qDebug () << response;
user_time = true;
}
void mainThingy::dataFrom2(QJsonDocument response)
{
qDebug () << response;
user_time = true;
}
void mainThingy::showErrReturn(QString err, int thread)
{
std::cout << "Error in " << thread << ": " << err.toStdString() << std::endl;
qDebug () << "Err " << 1 << err;
user_time = true;
}
void mainThingy::f_init1()
{
qDebug () << "void mainThingy::f_init1()";
emit init1();
}
void mainThingy::f_init2()
{
qDebug () << "void mainThingy::f_init2()";
emit init2();
}
void mainThingy::f_rq1()
{
qDebug () << "void mainThingy::f_rq1()";
emit runQr1();
}
void mainThingy::f_rq2()
{
qDebug () << "void mainThingy::f_rq2()";
emit runQr2();
}
void mainThingy::interface()
{
// Made a crude little CLI to get to the real problem
qDebug () << "void mainThingy::interface()";
std::cout << "Ready for command" << std::endl;
std::string usrResp;
std::cin >> usrResp;
QString uR = QString::fromStdString(usrResp);
if (uR == "i1")
{
f_init1();
user_time = false;
}
else if (uR == "i2")
{
f_init2();
user_time = false;
}
else if (uR == "q1")
{
f_rq1();
user_time = false;
}
else if (uR == "q2")
{
f_rq2();
user_time = false;
}
else if (uR == "quit")
{
exit (0);
}
else
{
std::cout << "?" << std::endl;
qDebug () << "??";
}
}
在
qrc:/conf1.ini
和 qrc:/conf2.ini
中有 2 个不同的配置,我希望 q1 和 q2 将数据发送到 2 个独立的数据库。
但是,我发现了以下几点:
qx::QxSqlDatabase::getSingleton()->getDatabase()
给出了一个错误和一个空数据库di1
时,查询工作正常并将数据插入到正确的数据库中,但是在同一程序实例中初始化 di2
时,我发现两个查询 "q1"
和 "q2"
将数据插入到初始化的数据库中di2
。本质上,相同的配置被覆盖。在 QxOrm 中使用多个数据库对于 SQL 数据库有 2 种使用方法。
QSqlDatabase
的对象,并在调用 setXXXX() 函数时传递指针,并在调用查询时使用该对象。true
传递 bJustForCurrentThread
,QxOrm 会根据文档进行处理。void setDriverName(const QString & s, bool bJustForCurrentThread = false, QSqlDatabase * pJustForThisDatabase = NULL);
void setDatabaseName(const QString & s, bool bJustForCurrentThread = false, QSqlDatabase * pJustForThisDatabase = NULL);
void setHostName(const QString & s, bool bJustForCurrentThread = false, QSqlDatabase * pJustForThisDatabase = NULL);
void setPort(int i, bool bJustForCurrentThread = false, QSqlDatabase * pJustForThisDatabase = NULL);
对于
QXMONGODB
驱动程序,您可以选择在不同线程中打开多个数据库,并且只要在调用 setXXXX() 函数时为 true
传递 bJustForCurrentThread
,它将按预期工作。
在上面的问题中,我没有在参数
true
中传递bJustForCurrentThread
,这导致为所有其他线程设置任何一个应用程序线程中的配置,从而出现了我遇到的问题。
结论:
QSqlDatabase
无法与 MONGODB 驱动程序一起使用,因为 QSqlDatabase
适用于 SQL 数据库call_query()
MONGODB 的实现表面上看起来有所不同,但内部实现仍然具有对不同线程中的多个数据库所需的支持。