我们可以归纳出数据库连接池的主要操作:
///
(1)首先建立一个数据库连接池对象
(2)初始化一定数量的数据库连接,放入连接池对象的容器中
(3)当有数据库访问请求时,直接从连接池的容器中得到一个连接,这里出现三种情况:
(a)当容器中的还有连接时,则返回给数据库访问请求者一个连接
(b)当容器中没有连接时,并且当前建立的连接数没有达到系统定义的最大连接数,则创建一个新的数据库连接。
#include<stdexcept>
#include<exception>
#include<stdio.h>
#include"connection_pool.h"
usingnamespace std;
usingnamespace sql;
ConnPool*ConnPool::connPool=NULL;
//连接池的构造函数
ConnPool::ConnPool(stringurl, 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=newConnPool("tcp://127.0.0.1:3306","root","root",50);
}
returnconnPool;
}
//初始化连接池,创建最大连接数的一半连接数量
voidConnPool::InitConnection(int iInitialSize)
{
Connection*conn;
pthread_mutex_lock(&lock);
for(inti=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);//建立连接
returnconn;
}
catch(sql::SQLException&e)
{
perror("创建连接出错");
returnNULL;
}
catch(std::runtime_error&e)
{
perror("运行时出错");
returnNULL;
}
}
//在连接池中获得一个连接
Connection*ConnPool::GetConnection(){
Connection*con;
pthread_mutex_lock(&lock);
if(connList.size()>0)//连接池容器中还有连接
{
con=connList.front();//得到第一个连接
connList.pop_front();//移除第一个连接
if(con->isClosed())//如果连接已经被关闭,删除后重新建立一个
{
deletecon;
con=this->CreateConnection();
}
//如果连接为空,则创建连接出错
if(con==NULL)
{
--curSize;
}
pthread_mutex_unlock(&lock);
returncon;
}
else{
if(curSize< maxSize){//还可以创建新的连接
con= this->CreateConnection();
if(con){
++curSize;
pthread_mutex_unlock(&lock);
returncon;
}
else{
pthread_mutex_unlock(&lock);
returnNULL;
}
}
else{//建立的连接数已经达到maxSize
pthread_mutex_unlock(&lock);
returnNULL;
}
}
}
//回收数据库连接
voidConnPool::ReleaseConnection(sql::Connection * conn){
if(conn){
pthread_mutex_lock(&lock);
connList.push_back(conn);
pthread_mutex_unlock(&lock);
}
}
//连接池的析构函数
ConnPool::~ConnPool()
{
this->DestoryConnPool();
}
//销毁连接池,首先要先销毁连接池的中连接
voidConnPool::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);
}
//销毁一个连接
voidConnPool::DestoryConnection(Connection* conn)
{
if(conn)
{
try{
conn->close();
}
catch(sql::SQLException&e)
{
perror(e.what());
}
catch(std::exception&e)
{
perror(e.what());
}
deleteconn;
}
}
(c)当容器中的没有连接并且当前建立的连接数达到系统定义的最大连接数,则当前访问数据库请求就要等待其他访问请求释放连接。
(4)当数据库访问完成后,应该将连接放回连接池的容器中。
(5)当服务停止时,需要先释放数据库连接池中的所有数据库连接,然后再释放数据库连接池对象。
2.编程实现:
头文件(connection_pool.h):
/*
*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>
usingnamespace std;
usingnamespace sql;
classConnPool{
private:
intcurSize;//当前已建立的数据库连接数量
intmaxSize;//连接池中定义的最大数据库连接数
stringusername;
stringpassword;
stringurl;
list<Connection*>connList;//连接池的容器队列
pthread_mutex_tlock;//线程锁
staticConnPool *connPool;
Driver*driver;
Connection*CreateConnection();//创建一个连接
voidInitConnection(int iInitialSize);//初始化数据库连接池
voidDestoryConnection(Connection *conn);//销毁数据库连接对象
voidDestoryConnPool();//销毁数据库连接池
ConnPool(stringurl,string user,string password,int maxSize);//构造方法
public:
~ConnPool();
Connection*GetConnection();//获得数据库连接
voidReleaseConnection(Connection *conn);//将数据库连接放回到连接池的容器中
staticConnPool *GetInstance();//获取数据库连接池对象
};
#endif /*_CONNECTION_POOL_H */
///