1. 程式人生 > >QT資料庫連線池的實現

QT資料庫連線池的實現

mysql.h檔案

#ifndef MYSQL
#define MYSQL

#include <QtSql>
#include <QQueue>
#include <QString>
#include <QMutex>
#include <QMutexLocker>
#include<QDebug>
#include<QSettings>//配置檔案

class ConnectionPool {
public:
    static void release(); // 關閉所有的資料庫連線
    static QSqlDatabase openConnection();                 // 獲取資料庫連線
    static void closeConnection(QSqlDatabase connection); // 釋放資料庫連接回連線池

    ~ConnectionPool();

private:
    static ConnectionPool& getInstance();

    ConnectionPool();
    ConnectionPool(const ConnectionPool &other);
    ConnectionPool& operator=(const ConnectionPool &other);
    QSqlDatabase createConnection(const QString &connectionName); // 建立資料庫連線

    QQueue<QString> usedConnectionNames;   // 已使用的資料庫連線名
    QQueue<QString> unusedConnectionNames; // 未使用的資料庫連線名

    // 資料庫資訊
    QString hostName;
    QString databaseName;
    QString username;
    QString password;
    QString databaseType;

    bool    testOnBorrow;    // 取得連線的時候驗證連線是否有效
    QString testOnBorrowSql; // 測試訪問資料庫的 SQL

    int maxWaitTime;  // 獲取連線最大等待時間
    int waitInterval; // 嘗試獲取連線時等待間隔時間
    int maxConnectionCount; // 最大連線數

    static QMutex mutex;
    static QWaitCondition waitConnection;
    static ConnectionPool *instance;
};


#endif // MYSQL


.cpp檔案
#include "mysql.h"
#include "login.h"
//#include <QDebug>


QMutex ConnectionPool::mutex;
QWaitCondition ConnectionPool::waitConnection;
ConnectionPool* ConnectionPool::instance = NULL;

ConnectionPool::ConnectionPool() {
    hostName     = "localhost";//主機名
    databaseName = "quick";//需要訪問的資料庫
    username     = "root";//使用者名稱
    password     = "****";//密碼
    databaseType = "QMYSQL";//資料庫型別

    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);
    }
}

ConnectionPool& ConnectionPool::getInstance() {
    if (NULL == instance) {
        QMutexLocker locker(&mutex);

        if (NULL == instance) {
            instance = new ConnectionPool();
        }
    }

    return *instance;
}

void ConnectionPool::release() {
    QMutexLocker locker(&mutex);
    delete instance;
    instance = NULL;
}

QSqlDatabase ConnectionPool::openConnection() {
    ConnectionPool& pool = ConnectionPool::getInstance();
    QString connectionName;

    QMutexLocker locker(&mutex);

    // 已建立連線數
    int connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();

    // 如果連線已經用完,等待 waitInterval 毫秒看看是否有可用連線,最長等待 maxWaitTime 毫秒
    for (int i = 0;
         i < pool.maxWaitTime
         && pool.unusedConnectionNames.size() == 0 && connectionCount == pool.maxConnectionCount;
         i += pool.waitInterval) {
        waitConnection.wait(&mutex, pool.waitInterval);

        // 重新計算已建立連線數
        connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();
    }

    if (pool.unusedConnectionNames.size() > 0) {
        // 有已經回收的連線,複用它們
        connectionName = pool.unusedConnectionNames.dequeue();
    } else if (connectionCount < pool.maxConnectionCount) {
        // 沒有已經回收的連線,但是沒有達到最大連線數,則建立新的連線
        connectionName = QString("Connection-%1").arg(connectionCount + 1);
    } else {
        // 已經達到最大連線數
        qDebug() << "Cannot create more connections.";
        return QSqlDatabase();
    }

    // 建立連線
    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();

    // 如果是我們建立的連線,從 used 裡刪除,放入 unused 裡
    if (pool.usedConnectionNames.contains(connectionName)) {
        QMutexLocker locker(&mutex);
        pool.usedConnectionNames.removeOne(connectionName);
        pool.unusedConnectionNames.enqueue(connectionName);
        waitConnection.wakeOne();
    }
}

QSqlDatabase ConnectionPool::createConnection(const QString &connectionName) {
    // 連線已經建立過了,複用它,而不是重新建立
    if (QSqlDatabase::contains(connectionName)) {
        QSqlDatabase db1 = QSqlDatabase::database(connectionName);

        if (testOnBorrow) {
            // 返回連線前訪問資料庫,如果連線斷開,重新建立連線
            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;
    }

    // 建立一個新的連線
    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;
}


相關推薦

QT資料庫連線實現

mysql.h檔案 #ifndef MYSQL #define MYSQL #include <QtSql> #include <QQueue> #include <QString> #include <QMutex> #i

servlet+jsp+mysql+資料庫連線實現註冊登陸驗證碼功能

首先專案的結構及所用到的jar包如圖: 主要用到jdbc和jstl的jar包,大家可自行去相應網站下載 一、資料庫和資料表的建立 1.建庫語句: create database test; 2.建表語句: CREATE TABLE `t_users` (  

自定義資料庫連線實現方式 MySQL

應用程式直接獲取資料庫連線缺點 使用者每次請求都會建立一次資料庫連線,並且資料庫建立連線會消耗相對大的資源和時間。 如果針對於個別的工具或者是大量的程式碼測試甚至系統執行,對資料庫操作次數頻繁,極大的佔用資料庫資源,有可能會發生宕機或者記憶體溢位的現象。 而在大多的專案中,常常用到阿里巴

JDBC資料庫連線實現原理(手動實現)

一、普通的資料庫連線     如下圖所示,個使用者獲取資料庫資料都要單獨建立一個jdbc連線,當用戶獲取資料完成後再將連線釋放,可見對cpu的資源消耗很大。  二

自定義資料庫連線實現方式 MySQL

應用程式直接獲取資料庫連線缺點 使用者每次請求都會建立一次資料庫連線,並且資料庫建立連線會消耗相對大的資源和時間。 如果針對於個別的工具或者是大量的程式碼測試甚至系統執行,對資料庫操作次數頻繁,極大的佔用資料庫資源,有可能會發生宕機或者記憶體溢位的現象。 而在大多的專案中

java資料庫連線實現原理

原文:http://blog.csdn.net/frightingforambition/article/details/25464129  一、為什麼在連線資料庫時要使用連線池  資料庫連線是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現得

自定義實現資料庫連線

資料庫連線池: >資料庫的連線物件建立工作,比較消耗效能 >一開始先在記憶體中開闢一塊空間(集合) , 先往池子裡面放置 多個連線物件。  後面需要連線的話,直接從池子裡面去。不要去自己建立連線了。  使用完畢, 要記得歸還連線。確保連線物件能迴圈利用。即建立

【Java】Spring和Tomcat自帶的連線實現資料庫操作

@[toc] 前言 前面我們已經用Spring和傳統的Jdbc實現資料庫操作、Spring和JdbcTemplate實現資料庫操作。但是這些都是基於直連的資料來源進行的,現在我們將介紹基於連線池的資料來源進行資料庫操作。前面幾個步驟都相同。 建立資料庫 首先建立我們的資料庫(這裡我使用的是Mysql)

理解資料庫連線底層原理之手寫實現

前言 資料庫連線池的基本思想是:為資料庫連線建立一個“緩衝池”,預先在池中放入一定數量的資料庫連線管道,需要時,從池子中取出管道進行使用,操作完畢後,在將管道放入池子中,從而避免了頻繁的向資料庫申請資源,釋放資源帶來的效能損耗。在如今的分散式系統當中,系統的QPS瓶頸往往就

Flask學習筆記之——藍圖、基於DBUtils實現資料庫連線、上下文管理等

面向物件知識回顧 子類繼承父類的三種方式 class Dog(Animal): #子類 派生類 def __init__(self,name,breed, life_value,aggr): # Animal.__init__(self

Flask學習【第3篇】:藍圖、基於DBUtils實現資料庫連線、上下文管理等 基於DBUtils實現資料庫連線

基於DBUtils實現資料庫連線池 小知識: 1、子類繼承父類的三種方式 class Dog(Animal): #子類 派生類 def

Java 使用動態代理和觀察者模式+threadlocal實現資料庫連線

當我們使用資料庫連線池時,如果多執行緒連線資料庫時,當超過5個執行緒連線資料庫時,那麼在第6個執行緒包括之後就連線不到資料庫了,該怎麼處理。 這裡用了java動態代理來這裡用了java的動態代理來代理資料庫的連線,攔截連線的close方法。並且給代理的連線加上一

python3.6實現mysql資料庫連線

首先安裝資料連線池模組 pip3 install DBUtils 然後安裝mysql驅動包 pip3 install PyMySQL 安裝完成之後,在專案中settings檔案裡面配置好資料連線資訊,如下圖: 新建一個myql_help檔案,名稱自己取,然後複製參考以下

基於DBUtils實現資料庫連線

小知識: 1、子類繼承父類的三種方式 class Dog(Animal): #子類 派生類 def __init__(self,name,breed, life_value,aggr): # Animal.__init__(self,nam

JDBC/InvocationHandler動態代理實現資料庫連線、資料來源

Java的JDBC程式設計中,資料庫的連線和關閉是十分耗費資源的。當對資料庫的訪問不是很頻繁時,可以在每次訪問資料庫時建立一個連線,用完之後關閉。但是,對於一個複雜的資料庫應用,頻繁的建立、關閉連線,會極大的減低系統性能,造成瓶頸。所以可以使用資料庫連線池來達到

Qt資料庫資料庫連線

在前面的章節裡,我們使用了下面的函式建立和取得資料庫連線: void createConnectionByName(const QString &connectionName) { QSqlDatabase db = QSqlDatabase::addDatabase("QMYS

資料庫連線 單例模式的實現

Java應用程式訪問資料庫的基本原理   在Java語言中,JDBC(Java DataBase Connection)是應用程式與資料庫溝通的橋樑,   即Java語言通過JDBC技術訪問資料庫。JDBC是一種“開放”的方案,它為資料庫應用開發人員﹑資料庫前臺工具開

資料庫連線底層原理以及手寫實現

資料庫連線池的基本思想是:為資料庫連線建立一個“緩衝池”,預先在池中放入一定數量的資料庫連線管道,需要時,從池子中取出管道進行使用,操作完畢後,在將管道放入池子中,從而避免了頻繁的向資料庫申請資源,釋放資源帶來的效能損耗。 在如今的分散式系統當中,系統的QPS瓶頸往往就

java之實現自己的資料庫連線

最近仿mybatis寫了一個自己的orm框架 專案已上傳到github上 https://github.com/skybluehhx/MYORM.git,既然是orm框架肯定需要事務管理器和資料庫連線池,下面將介紹我自己實現一個連線池 (主要藉助阻塞佇列) 首先定義一個介面

一個簡單資料庫連線實現

一、已實現功能   資料庫連線快取。將資料庫連線與執行緒ID繫結並提供執行資料庫操作時檢測。資料庫連線超時檢測。初始化資料庫環境,包括初始化資料庫,資料庫使用者,資料庫表。 二、程式碼列表: 1、MySqlDBManager:   用於管理資料庫配置、初始化資料庫環境及建立