欧美v国产v日韩v在线,欧美在线观看综合中文,777米奇色狠狠俺去啦,香蕉视频丝袜亚洲国产

返回列表
基于C++語(yǔ)言實(shí)現(xiàn)Qt框架下的數(shù)據(jù)庫(kù)連接池應(yīng)用

基于C++語(yǔ)言實(shí)現(xiàn)Qt框架下的數(shù)據(jù)庫(kù)連接池應(yīng)用

隨著互聯(lián)網(wǎng)和大數(shù)據(jù)時(shí)代的到來(lái),數(shù)據(jù)庫(kù)操作已經(jīng)成為許多企業(yè)和應(yīng)用程序不可或缺的重要部分。數(shù)據(jù)庫(kù)連接池技術(shù)的應(yīng)用,可以提高數(shù)據(jù)庫(kù)使用效率,減少資源和時(shí)間的浪費(fèi)?;贑++語(yǔ)言的Qt框架,也可以實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池技術(shù),本文將介紹如何使用Qt實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池,讓你的數(shù)據(jù)庫(kù)操作更加高效。

一、什么是數(shù)據(jù)庫(kù)連接池

數(shù)據(jù)庫(kù)連接池是一種通過(guò)預(yù)先建立多個(gè)數(shù)據(jù)庫(kù)連接,在應(yīng)用程序的運(yùn)行過(guò)程中重復(fù)利用數(shù)據(jù)庫(kù)連接的技術(shù)。通俗的說(shuō),就是在應(yīng)用程序中預(yù)先建立多個(gè)數(shù)據(jù)庫(kù)連接,當(dāng)需要訪問(wèn)數(shù)據(jù)庫(kù)時(shí)從連接池中獲取一個(gè)數(shù)據(jù)庫(kù)連接,用完后還回連接池中。這種利用池化技術(shù)的方式能夠降低新建連接的時(shí)間和資源消耗,提高數(shù)據(jù)庫(kù)的操作效率。下面,我們將使用Qt實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池。

二、Qt中數(shù)據(jù)庫(kù)連接的建立與使用

在Qt中,數(shù)據(jù)庫(kù)連接的建立與使用非常簡(jiǎn)單。首先需要?jiǎng)?chuàng)建一個(gè)QSqlDatabase實(shí)例,在該實(shí)例中設(shè)置需要連接的數(shù)據(jù)庫(kù)類型、主機(jī)和用戶名等信息。然后,使用QSqlDatabase::open()函數(shù)打開(kāi)該數(shù)據(jù)庫(kù)連接,并進(jìn)行一些操作。

#include <QSqlDatabase >

#include <QSqlQuery>

#include <QDebug>

QSqlDatabase db = QSqlDatabase::addDatabase(“QMYSQL”);

db.setHostName(“l(fā)ocalhost”);

db.setDatabaseName(“test”);

db.setUserName(“root”);

db.setPassword(“password”);

if(db.open())

{

qDebug() << “Open database success !”;

QSqlQuery query(db);

query.exec(“select * from testDB”);

while(query.next())

qDebug() << query.value(0).toString();

}

上述代碼演示了在Qt中連接MySQL數(shù)據(jù)庫(kù)的過(guò)程。首先使用QSqlDatabase::addDatabase(“QMYSQL”)函數(shù)創(chuàng)建一個(gè)QSqlDatabase實(shí)例,在該實(shí)例中設(shè)置需要連接的數(shù)據(jù)庫(kù)類型、主機(jī)和用戶名等信息。然后,使用QSqlDatabase::open()函數(shù)打開(kāi)該數(shù)據(jù)庫(kù)連接。在數(shù)據(jù)庫(kù)連接成功后,使用QSqlQuery實(shí)例進(jìn)行一些操作。注意,一定要在使用完QSqlQuery對(duì)象后,調(diào)用其~QSqlQuery()函數(shù)釋放資源。

三、Qt實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池

下面,我們將基于Qt實(shí)現(xiàn)一個(gè)簡(jiǎn)單的數(shù)據(jù)庫(kù)連接池。創(chuàng)建一個(gè)ConnectionPool類,該類中包含了多個(gè)數(shù)據(jù)庫(kù)連接對(duì)象。ConnectionPool的.h文件內(nèi)容如下:

#ifndef CONNECTIONPOOL_H

#define CONNECTIONPOOL_H

#include <QtSql>

#include <QQueue>

#include <QString>

#include <QMutex>

#include <QMutexLocker>

#include<QDebug>

#include<QSettings>//配置文件

class ConnectionPool {

public:

    static void release();                                // 關(guān)閉所有的數(shù)據(jù)庫(kù)連接

    static QSqlDatabase openConnection();                 // 獲取數(shù)據(jù)庫(kù)連接

    static void closeConnection(QSqlDatabase connection); // 釋放數(shù)據(jù)庫(kù)連接回連接池

    ~ConnectionPool();

private:

    static ConnectionPool& getInstance();

    ConnectionPool();

    ConnectionPool(const ConnectionPool &other);

    ConnectionPool& operator=(const ConnectionPool &other);

    QSqlDatabase createConnection(const QString &connectionName); // 創(chuàng)建數(shù)據(jù)庫(kù)連接

    QQueue<QString> usedConnectionNames;   // 已使用的數(shù)據(jù)庫(kù)連接名

    QQueue<QString> unusedConnectionNames; // 未使用的數(shù)據(jù)庫(kù)連接名

    // 數(shù)據(jù)庫(kù)信息

    QString hostName;

    QString databaseName;

    QString username;

    QString password;

    QString databaseType;

    bool    testOnBorrow;    // 取得連接的時(shí)候驗(yàn)證連接是否有效

    QString testOnBorrowSql; // 測(cè)試訪問(wèn)數(shù)據(jù)庫(kù)的 SQL

    int maxWaitTime;         // 獲取連接最大等待時(shí)間

    int waitInterval;        // 嘗試獲取連接時(shí)等待間隔時(shí)間

    int maxConnectionCount;  // 最大連接數(shù)

    static QMutex mutex;

    static QWaitCondition waitConnection;

    static ConnectionPool *instance;

};

#endif // CONNECTIONPOOL

SqlDatabase是Qt框架中操作數(shù)據(jù)庫(kù)的重要類之一,可以通過(guò)該類實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接的建立和操作。ConnectionPool類是自定義的一個(gè)庫(kù)連接池類,在該類中定義了數(shù)據(jù)庫(kù)連接的各種屬性,并包含了多個(gè)數(shù)據(jù)庫(kù)連接對(duì)象。

在ConnectionPool類的實(shí)現(xiàn)文件中,我們將實(shí)現(xiàn)具體的方法。定義如下靜態(tài)變量:

QMutex ConnectionPool::mutex;

QWaitCondition ConnectionPool::waitConnection;

ConnectionPool* ConnectionPool::instance = nullptr;

用靜態(tài)變量ConnectionPool::instance來(lái)存儲(chǔ)ConnectionPool類的唯一實(shí)例,同時(shí)使用QMutex和QWaitCondition分別保護(hù)多線程的同步和條件變量的使用。

接著,實(shí)現(xiàn)單態(tài)模式中的getInstance()方法。該方法用于返回ConnectionPool類的唯一實(shí)例:

ConnectionPool& ConnectionPool::getInstance() {

    if (nullptr == instance) {

        QMutexLocker locker(&mutex);

        if (nullptr == instance) {

            instance = new ConnectionPool();

        }

    }

    return *instance;

}

在getInstance ()方法中,使用互斥鎖QMutexLocker保證了多線程同步,使用雙重檢查鎖定機(jī)制確保了ConnectionPool類的唯一實(shí)例。

然后,我們可以實(shí)現(xiàn)如下連接的建立與關(guān)閉方法openConnection()和closeConnection()。openConnection()方法用于從連接池中獲取一個(gè)數(shù)據(jù)庫(kù)連接,closeConnection()方法用于還回這個(gè)數(shù)據(jù)庫(kù)連接:

QSqlDatabase ConnectionPool::openConnection() {

    ConnectionPool& pool = ConnectionPool::getInstance();

    QString connectionName;

    QMutexLocker locker(&mutex);

    // 已創(chuàng)建連接數(shù)

    int connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();

    // 如果連接已經(jīng)用完,等待 waitInterval 毫秒看看是否有可用連接,最長(zhǎng)等待 maxWaitTime 毫秒

    for (int i = 0;

         i < pool.maxWaitTime

         && pool.unusedConnectionNames.size() == 0 && connectionCount == pool.maxConnectionCount;

         i += pool.waitInterval) {

        waitConnection.wait(&mutex, pool.waitInterval);

        // 重新計(jì)算已創(chuàng)建連接數(shù)

        connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();

    }

    if (pool.unusedConnectionNames.size() > 0) {

        // 有已經(jīng)回收的連接,復(fù)用它們

        connectionName = pool.unusedConnectionNames.dequeue();

    } else if (connectionCount < pool.maxConnectionCount) {

        // 沒(méi)有已經(jīng)回收的連接,但是沒(méi)有達(dá)到最大連接數(shù),則創(chuàng)建新的連接

        connectionName = QString("Connection-%1").arg(connectionCount + 1);

    } else {

        // 已經(jīng)達(dá)到最大連接數(shù)

        qDebug() << "Cannot create more connections.";

        return QSqlDatabase();

    }

    // 創(chuàng)建連接

    QSqlDatabase db = pool.createConnection(connectionName);

    // 有效的連接才放入 usedConnectionNames

    if (db.isOpen()) {

        pool.usedConnectionNames.enqueue(connectionName);

    }

    return db;

}

void ConnectionPool::closeConnection(QSqlDatabase connection) {

    ConnectionPool& pool = ConnectionPool::getInstance();

    QString connectionName = connection.connectionName();

    // 如果是我們創(chuàng)建的連接,從 used 里刪除,放入 unused 里

    if (pool.usedConnectionNames.contains(connectionName)) {

        QMutexLocker locker(&mutex);

        pool.usedConnectionNames.removeOne(connectionName);

        pool.unusedConnectionNames.enqueue(connectionName);

        waitConnection.wakeOne();

    }

}

在openConnection()方法中,首先獲取互斥鎖QMutexLock,在連接池中查找是否有空閑連接。如果有,直接返回該連接,否則查看可用的連接數(shù)是否達(dá)到上限,如果沒(méi)有,則創(chuàng)建新的連接。當(dāng)新連接創(chuàng)建成功后,檢查該連接是否打開(kāi),如果打開(kāi),則更新連接數(shù)。最后釋放互斥鎖。

closeConnection()方法用于還回連接到連接池中,并檢查連接池中連接數(shù)量是否超過(guò)設(shè)定的更大值,如果超過(guò),則移除最早的連接。程序執(zhí)行完該方法后,也應(yīng)該釋放互斥鎖。

我們實(shí)現(xiàn)ConnectionPool的構(gòu)造函數(shù)和析構(gòu)函數(shù):

ConnectionPool::ConnectionPool() {

    hostName     = "127.0.0.1";//主機(jī)名

    databaseName = "DRIVER={SQL SERVER};SERVER=127.0.0.1;DATABASE=testDB";//需要訪問(wèn)的數(shù)據(jù)庫(kù)

    username     = "sa";      //用戶名

    password     = "123456";  //密碼

    databaseType = "QODBC";   //數(shù)據(jù)庫(kù)類型

    testOnBorrow = true;

    testOnBorrowSql = "SELECT 1";

    maxWaitTime  = 1000;

    waitInterval = 200;

    maxConnectionCount  = 1000;

}

ConnectionPool::~ConnectionPool() {

    // 銷毀連接池的時(shí)候刪除所有的連接

    foreach(QString connectionName, usedConnectionNames) {

        QSqlDatabase::removeDatabase(connectionName);

    }

    foreach(QString connectionName, unusedConnectionNames) {

        QSqlDatabase::removeDatabase(connectionName);

    }

}

void ConnectionPool::release() {

    QMutexLocker locker(&mutex);

    delete instance;

    instance = nullptr;

}

QSqlDatabase ConnectionPool::createConnection(const QString &connectionName) {

    // 連接已經(jīng)創(chuàng)建過(guò)了,復(fù)用它,而不是重新創(chuàng)建

    if (QSqlDatabase::contains(connectionName)) {

        QSqlDatabase db1 = QSqlDatabase::database(connectionName);

        if (testOnBorrow) {

            // 返回連接前訪問(wèn)數(shù)據(jù)庫(kù),如果連接斷開(kāi),重新建立連接

            qDebug() << "Test connection on borrow, execute:" << testOnBorrowSql << ", for" << connectionName;

            QSqlQuery query(testOnBorrowSql, db1);

            if (query.lastError().type() != QSqlError::NoError && !db1.open()) {

                qDebug() << "Open datatabase error:" << db1.lastError().text();

                return QSqlDatabase();

            }

        }

        return db1;

    }

    // 創(chuàng)建一個(gè)新的連接  注意:如果需要跨線程操作時(shí)這里需要連接時(shí)需要設(shè)置個(gè)靜態(tài)連接數(shù)據(jù)庫(kù)

    QSqlDatabase db = QSqlDatabase::addDatabase(databaseType, connectionName);

    db.setHostName(hostName);

    db.setDatabaseName(databaseName);

    db.setUserName(username);

    db.setPassword(password);

    db.setPort(3306);

    if (!db.open()) {

        qDebug() << "Open datatabase error:" << db.lastError().text();

        return QSqlDatabase();

    }

    return db;

}

在ConnectionPool類的構(gòu)造函數(shù)中,預(yù)先創(chuàng)建maxConnectionCount個(gè)數(shù)據(jù)庫(kù)連接,并存儲(chǔ)在usedConnectionNames中。在該構(gòu)造函數(shù)調(diào)用后,用戶可以直接通過(guò)openConnection()方法獲取連接,加快數(shù)據(jù)庫(kù)操作的速度。

數(shù)據(jù)庫(kù)連接長(zhǎng)時(shí)間不操作是可能會(huì)斷開(kāi),檢查數(shù)據(jù)庫(kù)的配置連接時(shí)間,一般會(huì)有時(shí)間限制,建議你程序啟動(dòng)需要和數(shù)據(jù)庫(kù)交互時(shí),先判斷數(shù)據(jù)庫(kù)是否是連接狀態(tài),未連接時(shí)重新連接。

關(guān)于qt中數(shù)據(jù)庫(kù)連接池的介紹到此就結(jié)束了。


如有侵權(quán),聯(lián)系刪除。

網(wǎng)站編輯:小優(yōu)智能科技有限公司 發(fā)布時(shí)間:Nov 08,2023
給我們留言
驗(yàn)證碼