c++ 連接mysql類

文章來源:http://hi.baidu.com/lbxthinker/blog/item/9b837b0f8a306fdb7acbe113.html

 

connpool.h文件

/**
*數據庫連接池(單例模式)
*
*@authour libingxiang
*
*@email [email protected]
**/
#ifndef CONN_POOL_H
#define CONN_POOL_H

#include <mysql_connection.h>
#include <mysql_driver.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include "push.h"
#include "mutex.h"

using namespace std;

class ConnPool{
private:
deque<sql::Connection *> conns;//連接隊列
int curSize;//當前隊列中路連接數目
int maxSize;//最大連接數目
sql::ConnectOptionsMap connectionProperties;
Mutex *lock;//連接隊列互斥鎖
static ConnPool * connPool;
sql::Driver * driver;//mysql connector C++ driver
sql::Connection * CreateConnection();//創建一個連接
void TerminateConnection(sql::Connection * conn);//終止一個連接
void Init(int initialSize);//初始化連接池
void Destroy();//銷燬連接池
protected:
ConnPool(string host,string user,string password,int maxSize);
public:
~ConnPool();
sql::Connection * GetConnection();//獲取一個連接
void ReleaseConnection(sql::Connection * conn);//釋放一個連接
sql::Connection * GetConnectionTry(int maxNum);//GetConnection的加強版,maxNum代表重試次數
static ConnPool * GetInstance();//獲取一個ConnPool對象實例
};

#endif

connpool.cpp文件

/**
*數據庫連接池
*
*@authour libingxiang
*
*@email [email protected]
**/
#include <stdexcept>
#include "connpool.h"
#include "config.h"

using namespace std;
extern Config *config;

ConnPool * ConnPool::connPool = NULL;

ConnPool::ConnPool(string host,string user,string password,int maxSize){
connectionProperties["hostName"] = host;
connectionProperties["userName"] = user;
connectionProperties["password"] = password;
connectionProperties["OPT_CONNECT_TIMEOUT"] = 600;
connectionProperties["OPT_RECONNECT"] = true;

this->maxSize = maxSize;
this->lock = new Mutex();
this->curSize = 0;
//初始化driver
try{
this->driver = sql::mysql::get_driver_instance(); //這裏不是線程安全的
}
catch(sql::SQLException &e){
string errorMsg = string("SQLException: ") + e.what() + string(" MySQL error code: ") + int_to_string(e.getErrorCode()) + string(" SQLState ") + e.getSQLState();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
}
catch(std::runtime_error &e){
string errorMsg = string("runtime_error: ") + e.what();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
}
//初始化連接池
this->Init(maxSize/2);
}

ConnPool::~ConnPool(){
this->Destroy();
delete lock;
}

ConnPool *ConnPool::GetInstance(){
if(connPool == NULL) {
connPool = new ConnPool(config->GetVar("db_host"),config->GetVar("db_user"),config->GetVar("db_password"),string_to_int(config->GetVar("max_db_conn_size")));
}

return connPool;
}

void ConnPool::Init(int size){
sql::Connection * conn ;
lock->Lock();

for(int i = 0; i < size ;){
conn = this->CreateConnection();
if(conn){
i++;
conns.push_back(conn);
++curSize;
}
else{
Log::Write(__FILE__,__FUNCTION__,__LINE__,"Init connpooo fail one");
}
}

lock->UnLock();
}

void ConnPool::Destroy(){
deque<sql::Connection *>::iterator pos;

lock->Lock();

for(pos = conns.begin(); pos != conns.end();++pos){
this->TerminateConnection(*pos);
}

curSize = 0;
conns.clear();

lock->UnLock();
}

sql::Connection * ConnPool::CreateConnection(){//這裏不負責curSize的增加
sql::Connection *conn;

try{
conn = driver->connect(connectionProperties);
Log::Write(__FILE__,__FUNCTION__,__LINE__,"create a mysql conn");
return conn;
}
catch(sql::SQLException &e){
string errorMsg = string("SQLException:") + e.what() + string(" MySQL error code: ") + int_to_string(e.getErrorCode()) + string(" SQLState ") + e.getSQLState();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
return NULL;
}
catch(std::runtime_error &e){
string errorMsg = string("runtime_error: ") + e.what();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
return NULL;
}
}

void ConnPool::TerminateConnection(sql::Connection * conn){
if(conn){
try{
conn->close();
}
catch(sql::SQLException &e){
string errorMsg = string("SQLException:") + e.what() + string(" MySQL error code: ") + int_to_string(e.getErrorCode()) + string(" SQLState ") + e.getSQLState();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
}
catch(std::runtime_error &e){
string errorMsg = string("runtime_error: ") + e.what();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
}

delete conn;
}
}

sql::Connection * ConnPool::GetConnection(){
sql::Connection * conn;

lock->Lock();

if(conns.size() > 0){//有空閒連接,則返回
conn = conns.front();
conns.pop_front();

if(conn->isClosed()){ //如果連接關閉,則重新打開一個連接
Log::Write(__FILE__,__FUNCTION__,__LINE__,"a mysql conn has been closed");
delete conn;
conn = this->CreateConnection();
}

if(conn == NULL){ //創建連接不成功
--curSize;
}
lock->UnLock();

return conn;
}
else{
if(curSize < maxSize){//還可以創建新的連接
conn = this->CreateConnection();
if(conn){
++curSize;
lock->UnLock();
return conn;
}
else{
lock->UnLock();
return NULL;
}
}
else{//連接池已經滿了
lock->UnLock();
return NULL;
}
}
}

void ConnPool::ReleaseConnection(sql::Connection * conn){
if(conn){
lock->Lock();

conns.push_back(conn);

lock->UnLock();
}
}

sql::Connection * ConnPool::GetConnectionTry(int maxNum){
sql::Connection * conn;

for(int i = 0; i < maxNum; ++i){
conn = this->GetConnection();
if(conn){
return conn;
}
else {
sleep(2);
}
}

return NULL;
}

 

 

實現是基於mysql connector C++ api的

magicdb.h文件

/**
*mysql connector C++ 封裝
*
*@authour libingxiang
*
*@email [email protected]
*
**/
#ifndef MAGICDB_H
#define MAGICDB_H

#include <mysql_connection.h>
#include <mysql_driver.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include "push.h"
#include "connpool.h"

using namespace std;

class MagicDB {
private:
ConnPool *connPool;
public:
MagicDB();
~MagicDB();
sql::ResultSet *Query(const string &database,const string &sql);
int Execute(const string &database,const string &sql);
};

#endif

magicdb.cpp文件

/**
*mysql connector C++ 封裝
*
*@authour libingxiang
*
*@email [email protected]
*
**/
#include <stdexcept>
#include "magicdb.h"
#include "log.h"
#include "util.h"

using namespace std;

MagicDB::MagicDB(){
this->connPool = ConnPool::GetInstance();
}

sql::ResultSet * MagicDB::Query(const string &database,const string &sql){
sql::Connection *conn;
sql::Statement *stmt;
sql::ResultSet *res;

try{
conn = connPool->GetConnection(); //從連接池中獲取連接
if(conn == NULL){
conn = connPool->GetConnectionTry(2);
if(conn == NULL){
Log::Write(__FILE__,__FUNCTION__,__LINE__,"query get conn error");
return NULL;
}
}

conn->setSchema(database);
stmt = conn->createStatement();
res = stmt->executeQuery(sql.c_str());

connPool->ReleaseConnection(conn);//將連接放入連接池中

delete stmt;
return res;
}
catch(sql::SQLException &e){
string errorMsg = string("SQLException:") + e.what() + string(" MySQL error code: ") + int_to_string(e.getErrorCode()) + string(" SQLState ") + e.getSQLState();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);

connPool->ReleaseConnection(conn);//將連接放入連接池中

delete stmt;
delete res;
return NULL;
}
catch(std::runtime_error &e){
string errorMsg = string("runtime_error: ") + e.what();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);

connPool->ReleaseConnection(conn);//將連接放入連接池中

delete stmt;
delete res;
return NULL;
}
}

int MagicDB::Execute(const string &database,const string &sql){
sql::Statement * stmt;
sql::Connection *conn;

try{
conn = connPool->GetConnection(); //從連接池中獲取連接
if(conn == NULL){
conn = connPool->GetConnectionTry(2);
if(conn == NULL){
Log::Write(__FILE__,__FUNCTION__,__LINE__,"query get conn error");
return -3;
}
}

conn->setSchema(database);
stmt = conn->createStatement();
stmt->execute(sql.c_str());

connPool->ReleaseConnection(conn);//將連接放入連接池中

delete stmt;
return 0;
}
catch(sql::SQLException &e){
string errorMsg = string("SQLException:") + e.what() + string(" MySQL error code: ") + int_to_string(e.getErrorCode()) + string(" SQLState ") + e.getSQLState();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);

connPool->ReleaseConnection(conn);//將連接放入連接池中

delete stmt;
return -1;
}
catch(std::runtime_error &e){
string errorMsg = string("runtime_error: ") + e.what();
Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);

connPool->ReleaseConnection(conn);//將連接放入連接池中

delete stmt;
return -2;
}
}

MagicDB::~MagicDB(){
delete connPool;
}

發佈了12 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章