1. 程式人生 > >基於MySQL Connector/C++的資料庫連線池

基於MySQL Connector/C++的資料庫連線池

本文來自:http://www.oschina.net/code/snippet_583625_19818
/*
 *File: connection_pool.h
 *Author: csc
 */
 
#ifndef _CONNECTION_POOL_H
#define _CONNECTION_POOL_H
 
#include <mysql_connection.h>
#include <mysql_driver.h>
#include <cppconn/exception.h>
#include <cppconn/driver.h>
#include <cppconn/connection.h>
#include <cppconn/resultset.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/statement.h>
#include <pthread.h>
#include <list>
 
using namespace std;
using namespace sql;
 
class ConnPool {
private:
    int curSize; //當前已建立的資料庫連線數量
    int maxSize; //連線池中定義的最大資料庫連線數
    string username;
    string password;
    string url;
    list<Connection*> connList; //連線池的容器佇列
    pthread_mutex_t lock; //執行緒鎖
    static ConnPool *connPool;
    Driver*driver;
 
    Connection*CreateConnection(); //建立一個連線
    void InitConnection(int iInitialSize); //初始化資料庫連線池
    void DestoryConnection(Connection *conn); //銷燬資料庫連線物件
    void DestoryConnPool(); //銷燬資料庫連線池
    ConnPool(string url, string user, string password, int maxSize); //構造方法
public:
    ~ConnPool();
    Connection*GetConnection(); //獲得資料庫連線
    void ReleaseConnection(Connection *conn); //將資料庫連線放回到連線池的容器中
    static ConnPool *GetInstance(); //獲取資料庫連線池物件
};
#endif  /*_CONNECTION_POOL_H */
/*
 * connection_pool.cpp
 *
 *  Created on: 2013-3-29
 *      Author: csc
 */
 
#include <stdexcept>
#include <exception>
#include <stdio.h>
#include "connection_pool.h"
 
using namespace std;
using namespace sql;
 
ConnPool *ConnPool::connPool = NULL;
 
//連線池的建構函式
ConnPool::ConnPool(string url, string userName, string password, int maxSize) {
    this->maxSize = maxSize;
    this->curSize = 0;
    this->username = userName;
    this->password = password;
    this->url = url;
    try {
        this->driver = sql::mysql::get_driver_instance();
    } catch (sql::SQLException&e) {
        perror("驅動連接出錯;\n");
    } catch (std::runtime_error&e) {
        perror("執行出錯了\n");
    }
    this->InitConnection(maxSize / 2);
}
 
//獲取連線池物件,單例模式
ConnPool*ConnPool::GetInstance() {
    if (connPool == NULL) {
        connPool = new ConnPool("tcp://127.0.0.1:3306", "root", "123456", 50);
    }
    return connPool;
}
 
//初始化連線池,建立最大連線數的一半連線數量
void ConnPool::InitConnection(int iInitialSize) {
    Connection*conn;
    pthread_mutex_lock(&lock);
    for (int i = 0; i < iInitialSize; i++) {
        conn = this->CreateConnection();
        if (conn) {
            connList.push_back(conn);
            ++(this->curSize);
        } else {
            perror("建立CONNECTION出錯");
        }
    }
    pthread_mutex_unlock(&lock);
}
 
//建立連線,返回一個Connection
Connection* ConnPool::CreateConnection() {
    Connection*conn;
    try {
        conn = driver->connect(this->url, this->username, this->password); //建立連線
        return conn;
    } catch (sql::SQLException&e) {
        perror("建立連接出錯");
        return NULL;
    } catch (std::runtime_error&e) {
        perror("執行時出錯");
        return NULL;
    }
}
 
//在連線池中獲得一個連線
Connection*ConnPool::GetConnection() {
    Connection*con;
    pthread_mutex_lock(&lock);
 
    if (connList.size() > 0) {   //連線池容器中還有連線
        con = connList.front(); //得到第一個連線
        connList.pop_front();   //移除第一個連線
        if (con->isClosed()) {   //如果連線已經被關閉,刪除後重新建立一個
            delete con;
            con = this->CreateConnection();
        }
        //如果連線為空,則建立連接出錯
        if (con == NULL) {
            --curSize;
        }
        pthread_mutex_unlock(&lock);
        return con;
    } else {
        if (curSize < maxSize) { //還可以建立新的連線
            con = this->CreateConnection();
            if (con) {
                ++curSize;
                pthread_mutex_unlock(&lock);
                return con;
            } else {
                pthread_mutex_unlock(&lock);
                return NULL;
            }
        } else { //建立的連線數已經達到maxSize
            pthread_mutex_unlock(&lock);
            return NULL;
        }
    }
}
 
//回收資料庫連線
void ConnPool::ReleaseConnection(sql::Connection * conn) {
    if (conn) {
        pthread_mutex_lock(&lock);
        connList.push_back(conn);
        pthread_mutex_unlock(&lock);
    }
}
 
//連線池的解構函式
ConnPool::~ConnPool() {
    this->DestoryConnPool();
}
 
//銷燬連線池,首先要先銷燬連線池的中連線
void ConnPool::DestoryConnPool() {
    list<Connection*>::iterator icon;
    pthread_mutex_lock(&lock);
    for (icon = connList.begin(); icon != connList.end(); ++icon) {
        this->DestoryConnection(*icon); //銷燬連線池中的連線
    }
    curSize = 0;
    connList.clear(); //清空連線池中的連線
    pthread_mutex_unlock(&lock);
}
 
//銷燬一個連線
void ConnPool::DestoryConnection(Connection* conn) {
    if (conn) {
        try {
            conn->close();
        } catch (sql::SQLException&e) {
            perror(e.what());
        } catch (std::exception&e) {
            perror(e.what());
        }
        delete conn;
    }
}


/*
 * main.cpp
 *
 *  Created on: 2013-3-26
 *      Author: holy
 */
 
#include "connection_pool.h"
 
namespace ConnectMySQL {
 
//初始化連線池
ConnPool *connpool = ConnPool::GetInstance();
 
void run() {
 
    Connection *con;
    Statement *state;
    ResultSet *result;
 
    // 從連線池中獲取mysql連線
    con = connpool->GetConnection();
 
    state = con->createStatement();
    state->execute("use holy");
 
    // 查詢
    result = state->executeQuery("select * from student where id < 1002");
 
    // 輸出查詢
    while (result->next()) {
        int id = result->getInt("id");
        string name = result->getString("name");
        cout << id << " : " << name << endl;
    }
    delete state;
    connpool->ReleaseConnection(con);
}
}
 
int main(int argc, char* argv[]) {
    ConnectMySQL::run();
    return 0;
}