Qt中的数据库连接池

时间:2017-11-16 05:34:24

标签: c++ multithreading qt

我有Qt应用程序,它有<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="toggler_container"> <select name="select" id="aaa"> <option value="0">---</option> <option value="1">AAA</option> <option value="2">BBB</option> </select> <select name="select" id="bbb"> <option value="0">---</option> <option value="1">AAA</option> <option value="2">BBB</option> </select> <select name="select" id="ccc"> <option value="0">---</option> <option value="1">AAA</option> <option value="2">BBB</option> </select> </div>单例,只有一个DatabaseService实例,而且很多线程应该使用这个QSqlDatabase实例,当一些线程使用实例时,mutex会被锁定QSqlDatabase。但我明白这不是这项任务的最佳模式。

我应该在这里使用某种类型的数据库连接池还是这样的?我怎样才能在Qt中实现它?

请提供一些例子。

UPD:

一个实例已经的类有自己的线程,这个类会有多个实例:

的.cpp:

QSqlDatabase

DatabaseService:

·H:

//...

QFuture<QMap<QString, QString>> future = QtConcurrent::run(DatabaseService::executeQuery, sqlCommand);

future.waitForFinished();

//...

的.cpp:

class DatabaseService
{
public:
    //...
    static QMap<QString, QString> executeQuery(QString command);

private:
    static QThreadStorage<QSqlDatabase> mDatabasePool;
    static QSqlDatabase getDatabase();

};

UPD 2:

main.cpp中:

//...
QThreadStorage<QSqlDatabase> DatabaseService::mDatabasePool;

QSqlDatabase DatabaseService::getDatabase()
{
    if(DatabaseService::mDatabasePool.hasLocalData()) {
        return DatabaseService::mDatabasePool.localData();
    } else {
        auto database = QSqlDatabase::addDatabase("QPSQL", QUuid::createUuid().toString());
        database.setHostName("hostName");
        database.setDatabaseName("databaseName");
        database.setUserName("user");
        database.setPassword("password");
        DatabaseService::mDatabasePool.setLocalData(database);
        return database;
    }
}

QMap<QString,QString> DatabaseService::executeQuery(QString command){

    QSqlQuery query (DatabaseService::getDatabase());
    query.exec(command);

    //...

    return result;
}

//...

myserver.h:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyServer server;

    server.listen(QHostAddress::Any, 1234);

    return a.exec();
}

myserver.cpp:

class MyServer : public QTcpServer
{
    Q_OBJECT

    explicit MyServer(QObject *parent = 0);
    ~MyServer();

protected:
    void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE;

signals:
    void stopAll();
};

myclient.h:

MyServer::MyServer(QObject *parent) : QTcpServer(parent)
{

}

MyServer::~MyServer(){
    emit stopAll();
}

void MyServer::incomingConnection(qintptr socketDescriptor){
    QThread* clientThread = new QThread;
    MyClient *client = new MyClient(socketDescriptor, this);

    client->moveToThread(clientThread);

    connect(clientThread, SIGNAL(started()), client, SLOT(process()));

    connect(client, SIGNAL(finished()), clientThread, SLOT(quit()));
    connect(this, SIGNAL(stopAll()), client, SLOT(stopFromServer()));
    connect(client, SIGNAL(finished()), client, SLOT(deleteLater()));
    connect(clientThread, SIGNAL(finished()), clientThread, SLOT(deleteLater()));

    clientThread->start();
}

myclient.cpp:

class MyClient : public QObject
{
    Q_OBJECT
public:
    explicit MyClient(int socketDescriptor, MyServer *server);
    ~MyClient();

private:
    QSslSocket* socket = NULL;

public slots:
    void process();
}

1 个答案:

答案 0 :(得分:3)

我还使用数据库连接创建了一个软件。我不在我的应用程序上使用QThread但是使用QFuture并且线程将从全局线程池中获取(通常,线程池的数量将是CPU线程的数量)。

访问数据库时,每个池都有自己的QSqlDatabase。我使用QThreadStorage作为QSqlDatabase的存储。

static QThreadStorage<QSqlDatabase> mDatabasePool;
....
QSqlDatabase Db::getDatabase()
{
    if(mDatabasePool.hasLocalData()) {
        return mDatabasePool.localData();
    } else {
        auto database = QSqlDatabase::addDatabase(SQLDRIVERNAME[DBTYPE], QUuid::createUuid().toString());
        mDatabasePool.setLocalData(database);
        return database;
    }
}

因此,只有在线程没有连接时才会创建数据库连接。

对于完整示例项目,您可以查看我的项目:https://github.com/apinprastya/sultan。数据库位于libdb内,而工作者QFuture位于libserver中。您可以将它用作参考。但我不确定我的设计是否适合你。