MySql Connector/C++8是一个用于连接MySQL服务器的C++应用程序。Connector/C++8可用于访问实现文档存储的 MySQL服务器,或者使用SQL查询以传统方式访问。它支持使用XDevAPI开发C ++应用程序,或使用XDevAPI for C开发纯C应用程序,同时Connector/C++8还支持与之前使用Connector/C++1.1中基于JDBC的旧API开发的C++应用程序一起编译及开发(即:向后兼容)。但是,Connector/C++8的首选开发环境是使用XDevAPI或XDevAPI for C。
#pragma once
#include <mysqlconnector\mysql_connection.h>
#include <mysqlconnector\mysql_driver.h>
#include <condition_variable>
class CConnectPool
{
public:
CConnectPool();
~CConnectPool();
public:
//创建一个连接,返回一个Connection
sql::Connection * CreateConnection();
//创建连接池实例
static CConnectPool* GetInstance(const char *pUrl, const char *pDB, const char * pUserName, const char *pPwd);
//设置连接池大小
void SetPoolSize(int nMinSize, int nMaxSize);
//初始化连接
bool InitConnection();
//在连接池中获得一个连接
sql::Connection * GetConnection();
//回收数据库连接
void ReleaseConnection(sql::Connection *conn);
//销毁连接池,首先要销毁连接池中的连接
void DestroyPool();
//销毁一个连接
void DestroyConnection(sql::Connection *conn);
private:
//连接池的构造函数
CConnectPool(const char *pUrl, const char *pDB, const char * pUserName, const char *pPwd);
private:
int m_nMinSize;
int m_nMaxSize;
std::string strUrl;
std::string strUserName;
std::string strPwd;
std::string strDB;
std::list<sql::Connection *> m_listConn;//连接池容器队列
std::condition_variable m_variable;
std::mutex m_mtx;
static CConnectPool * pConnectPool;
sql::Driver * driver;
};
#include <iostream>
#include "ConnectPool.h"
CConnectPool * CConnectPool::pConnectPool = nullptr;
CConnectPool::CConnectPool()
{
}
CConnectPool::~CConnectPool()
{
}
sql::Connection * CConnectPool::CreateConnection()
{
sql::Connection *ptrConn = nullptr;
try
{
//建立连接
ptrConn = driver->connect(this->strUrl.c_str(), this->strUserName.c_str(), this->strPwd.c_str());
return ptrConn;
}
catch (sql::SQLException& e)
{
std::cout << "创建mysql连接出错:" << e.what() << std::endl;
return nullptr;
}
catch (std::runtime_error &e)
{
std::cout << "运行时出错:" << e.what() << std::endl;
return nullptr;
}
}
CConnectPool* CConnectPool::GetInstance(const char *pUrl, const char *pDB, const char * pUserName, const char *pPwd)
{
if (nullptr == pConnectPool)
{
pConnectPool = new CConnectPool(pUrl,pDB,pUserName,pPwd);
}
return pConnectPool;
}
void CConnectPool::SetPoolSize(int nMinSize, int nMaxSize)
{
m_nMaxSize = nMaxSize;
m_nMinSize = nMinSize;
}
bool CConnectPool::InitConnection()
{
sql::Connection *conn = nullptr;
std::lock_guard<std::mutex> lock(m_mtx);
size_t nSum = 0;
size_t nCount = m_nMaxSize > m_nMinSize ? m_nMaxSize : m_nMinSize;
for (size_t i = 0; i < nCount; ++i)
{
conn = this->CreateConnection();
if (conn)
{
m_listConn.push_back(conn);
nSum++;
}
}
if (nSum < nCount)
{
return false;
}
return true;
}
sql::Connection * CConnectPool::GetConnection()
{
sql::Connection *con = nullptr;
std::lock_guard<std::mutex> lock(m_mtx);
if (m_listConn.size() == 0)
{
return this->CreateConnection();
}
con = m_listConn.front();
m_listConn.pop_front();
if (!con->isClosed() && con->isValid())
{
return con;
}
else
{
return this->CreateConnection();
}
}
void CConnectPool::ReleaseConnection(sql::Connection *conn)
{
std::unique_lock<std::mutex> lock(m_mtx);
if (conn)
{
m_listConn.push_back(conn);
lock.unlock();
m_variable.notify_one();
}
}
void CConnectPool::DestroyPool()
{
std::unique_lock<std::mutex> lock(m_mtx);
for (auto it = m_listConn.begin(); it != m_listConn.end(); ++it)
{
//销毁连接池中的连接
this->DestroyConnection(*it);
}
//清空连接池中的连接
m_listConn.clear();
}
void CConnectPool::DestroyConnection(sql::Connection *conn)
{
if (conn)
{
try
{
conn->close();
}
catch (sql::SQLException &e)
{
std::cout << "销毁一个连接错误:" << e.what() << std::endl;
}
catch (std::exception &e)
{
std::cout << e.what() << std::endl;
}
delete conn;
conn = nullptr;
}
}
CConnectPool::CConnectPool(const char *pUrl, const char *pDB, const char * pUserName, const char *pPwd)
{
this->strUrl = pUrl;
this->strDB = pDB;
this->strUserName = pUserName;
this->strPwd = pPwd;
try
{
//获取mysql数据库驱动
this->driver = sql::mysql::get_driver_instance();
}
catch (sql::SQLException& e)
{
std::cout << "mysql驱动连接出错:" << e.what() << std::endl;
//可由自己的日志模块进行输出
}
catch (std::runtime_error& e)
{
std::cout << "mysql运行出错:" << e.what() << std::endl;
}
if (!this->InitConnection())
{
std::cout << "初始化连接池出错" << std::endl;
}
}
#pragma once
#include "ConnectPool.h"
#include <mysqlconnector\cppconn\resultset.h>
#include <mysqlconnector\cppconn\statement.h>
#include <vector>
class CMysqlDataBase
{
public:
CMysqlDataBase();
~CMysqlDataBase();
public:
static void CreateDataBase();
//登录数据库
virtual bool Login(int nMinPoolSize, int nMaxPoolSize);
//登出数据库
virtual void Logout();
//操作数据库
virtual bool RunSqlExec(const std::string & strsql);
virtual sql::ResultSet *RunSqlQuery(const std::string strsql);
virtual bool RunSqlExecTrans(const std::vector<std::string>& vecstrsql);
//设置数据库信息
virtual void SetDbSvrInfo(const char* pHost, unsigned short nHostPort, const char* pDbName);
//设置用户登录信息
virtual void SetUserLogInfo(const char* pUserName, const char* pPwd);
public:
static CMysqlDataBase *m_pMysql;
private:
CConnectPool *m_pConnPool;
std::string m_strDbName;
std::string m_strHostIp;
unsigned short m_nPort;
std::string m_strUserName;
std::string m_strPwd;
};
#include "MysqlDataBase.h"
#include <sstream>
CMysqlDataBase *CMysqlDataBase::m_pMysql = nullptr;
CMysqlDataBase::CMysqlDataBase()
{
}
CMysqlDataBase::~CMysqlDataBase()
{
}
void CMysqlDataBase::CreateDataBase()
{
if (nullptr == m_pMysql)
{
m_pMysql = new CMysqlDataBase();
}
}
bool CMysqlDataBase::Login(int nMinPoolSize, int nMaxPoolSize)
{
std::stringstream ss;
ss << "tcp://" << m_strHostIp << ":" << m_nPort << "/" << m_strDbName;
std::string strUrl = ss.str();
m_pConnPool = CConnectPool::GetInstance(strUrl.c_str(), m_strDbName.c_str(), m_strUserName.c_str(), m_strPwd.c_str());
if (!m_pConnPool)
{
std::cout << "获取连接池实例失败" << std::endl;
return false;
}
m_pConnPool->SetPoolSize(nMinPoolSize, nMaxPoolSize);
bool bResult = m_pConnPool->InitConnection();
if (bResult)
{
//初始化成功
//启动消息队列
}
else
return false;
return bResult;
}
void CMysqlDataBase::Logout()
{
m_pConnPool->DestroyPool();
}
bool CMysqlDataBase::RunSqlExec(const std::string & strsql)
{
sql::Connection *pConn = m_pConnPool->GetConnection();
if (!pConn)
{
std::cout << "运行时获取连接失败" << std::endl;
return false;
}
sql::Statement *state = pConn->createStatement();
//true:sql命令的提交(commit)由驱动程序负责
//false:sql命令的提交由应用程序负责,程序必须调用commit或者rollback方法
pConn->setAutoCommit(false);
try
{
state->execute("set character set gbk;");
///ddl存储过程中有返回是否成功的结果集,不能用 executupdate
state->execute(strsql.c_str());
do
{
state->getResultSet();
} while (state->getMoreResults());
pConn->commit();
pConn->setAutoCommit(true);
state->close();
delete state;
}
catch (sql::SQLException& e)
{
delete state;
m_pConnPool->ReleaseConnection(pConn);
std::cout << "Exec执行失败" << std::endl;
return false;
}
catch (const std::exception&)
{
delete state;
m_pConnPool->ReleaseConnection(pConn);
std::cout << "Exec执行失败" << std::endl;
return false;
}
m_pConnPool->ReleaseConnection(pConn);
return true;
}
sql::ResultSet *CMysqlDataBase::RunSqlQuery(const std::string strsql)
{
sql::Connection *pConn = m_pConnPool->GetConnection();
if (!pConn)
{
std::cout << "获取连接失败" << std::endl;
return nullptr;
}
sql::Statement *state = pConn->createStatement();
sql::ResultSet *result = nullptr;
try
{
state->execute("set character set gbk;");
result = state->executeQuery(strsql.c_str()); //用来查询数据库信息
do
{
state->getResultSet();
} while (state->getMoreResults());
state->close();
delete state;
}
catch (sql::SQLException& e)
{
delete state;
m_pConnPool->ReleaseConnection(pConn);
std::cout << "查询数据库失败:" << e.what() << std::endl;
return nullptr;
}
catch (const std::exception& e)
{
delete state;
m_pConnPool->ReleaseConnection(pConn);
std::cout << "查询数据库失败:" << e.what() << std::endl;
return nullptr;
}
m_pConnPool->ReleaseConnection(pConn);
return result;
}
bool CMysqlDataBase::RunSqlExecTrans(const std::vector<std::string>& vecstrsql)
{
sql::Connection *pConn = m_pConnPool->GetConnection();
if (!pConn)
{
std::cout << "获取数据库连接失败" << std::endl;
return false;
}
sql::Statement *state = pConn->createStatement();
pConn->setAutoCommit(false);
state->execute("set character set gbk;");
for (const auto &str : vecstrsql)
{
try
{
state->execute(str.c_str());
do
{
state->getResultSet();
} while (state->getMoreResults());
}
catch (sql::SQLException& e)
{
std::cout << "ExecTrans执行失败:" << e.what() << std::endl;
}
catch (const std::exception& e)
{
std::cout << "ExecTrans执行失败:" << e.what() << std::endl;
}
}
pConn->commit();
pConn->setAutoCommit(true);
state->close();
delete state;
m_pConnPool->ReleaseConnection(pConn);
return true;
}
void CMysqlDataBase::SetDbSvrInfo(const char* pHost, unsigned short nHostPort, const char* pDbName)
{
m_strHostIp = pHost;
m_nPort = nHostPort;
m_strDbName = pDbName;
}
void CMysqlDataBase::SetUserLogInfo(const char* pUserName, const char* pPwd)
{
m_strUserName = pUserName;
m_strPwd = pPwd;
}