国产精品视频被艹_九九自拍视频精品_亚洲国产清纯系在线观看_十八禁深夜福利老司机视频_熟女日韩精品2区_午夜激情经典日韩_亚洲国产成人欧美在线观看_中文字幕人成乱码熟女超碰_大陆一级成人毛片_18禁在线看网站

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

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

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

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

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

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

在Qt中,數(shù)據(jù)庫連接的建立與使用非常簡單。首先需要創(chuàng)建一個QSqlDatabase實例,在該實例中設(shè)置需要連接的數(shù)據(jù)庫類型、主機(jī)和用戶名等信息。然后,使用QSqlDatabase::open()函數(shù)打開該數(shù)據(jù)庫連接,并進(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ù)庫的過程。首先使用QSqlDatabase::addDatabase(“QMYSQL”)函數(shù)創(chuàng)建一個QSqlDatabase實例,在該實例中設(shè)置需要連接的數(shù)據(jù)庫類型、主機(jī)和用戶名等信息。然后,使用QSqlDatabase::open()函數(shù)打開該數(shù)據(jù)庫連接。在數(shù)據(jù)庫連接成功后,使用QSqlQuery實例進(jìn)行一些操作。注意,一定要在使用完QSqlQuery對象后,調(diào)用其~QSqlQuery()函數(shù)釋放資源。

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

下面,我們將基于Qt實現(xiàn)一個簡單的數(shù)據(jù)庫連接池。創(chuàng)建一個ConnectionPool類,該類中包含了多個數(shù)據(jù)庫連接對象。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ù)庫連接

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

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

    ~ConnectionPool();

private:

    static ConnectionPool& getInstance();

    ConnectionPool();

    ConnectionPool(const ConnectionPool &other);

    ConnectionPool& operator=(const ConnectionPool &other);

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

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

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

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

    QString hostName;

    QString databaseName;

    QString username;

    QString password;

    QString databaseType;

    bool    testOnBorrow;    // 取得連接的時候驗證連接是否有效

    QString testOnBorrowSql; // 測試訪問數(shù)據(jù)庫的 SQL

    int maxWaitTime;         // 獲取連接最大等待時間

    int waitInterval;        // 嘗試獲取連接時等待間隔時間

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

    static QMutex mutex;

    static QWaitCondition waitConnection;

    static ConnectionPool *instance;

};

#endif // CONNECTIONPOOL

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

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

QMutex ConnectionPool::mutex;

QWaitCondition ConnectionPool::waitConnection;

ConnectionPool* ConnectionPool::instance = nullptr;

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

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

ConnectionPool& ConnectionPool::getInstance() {

    if (nullptr == instance) {

        QMutexLocker locker(&mutex);

        if (nullptr == instance) {

            instance = new ConnectionPool();

        }

    }

    return *instance;

}

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

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

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 毫秒看看是否有可用連接,最長等待 maxWaitTime 毫秒

    for (int i = 0;

         i < pool.maxWaitTime

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

         i += pool.waitInterval) {

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

        // 重新計算已創(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) {

        // 沒有已經(jīng)回收的連接,但是沒有達(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á)到上限,如果沒有,則創(chuàng)建新的連接。當(dāng)新連接創(chuàng)建成功后,檢查該連接是否打開,如果打開,則更新連接數(shù)。最后釋放互斥鎖。

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

我們實現(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";//需要訪問的數(shù)據(jù)庫

    username     = "sa";      //用戶名

    password     = "123456";  //密碼

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

    testOnBorrow = true;

    testOnBorrowSql = "SELECT 1";

    maxWaitTime  = 1000;

    waitInterval = 200;

    maxConnectionCount  = 1000;

}

ConnectionPool::~ConnectionPool() {

    // 銷毀連接池的時候刪除所有的連接

    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)建過了,復(fù)用它,而不是重新創(chuàng)建

    if (QSqlDatabase::contains(connectionName)) {

        QSqlDatabase db1 = QSqlDatabase::database(connectionName);

        if (testOnBorrow) {

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

            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)建一個新的連接  注意:如果需要跨線程操作時這里需要連接時需要設(shè)置個靜態(tài)連接數(shù)據(jù)庫

    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個數(shù)據(jù)庫連接,并存儲在usedConnectionNames中。在該構(gòu)造函數(shù)調(diào)用后,用戶可以直接通過openConnection()方法獲取連接,加快數(shù)據(jù)庫操作的速度。

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

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


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

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