网站建设知识
MYSQL C API 封装和MYSQL连接池
2025-07-22 10:01  点击:0

注意:

1、如果查询到的数据有多条需要把SQL语句重复执行。

2、执行完毕select语句并没有数据的时候请注意调用ClearResult函数进行记录集指针清理,不然下次同样的SQL执行会得到自己不要的数据。如果上次SQL语句和本次SQL语句不一样的话不存在这样的问题,内部会根据SQL对比不同的时候会自动清理旧的记录集数据。

源码下载地址:MYSQL CODE 封装下载地址

代码:

mysql 类封装 头文件源码如下:

#pragma once#include #include #include #include #include #include #include "mysql/mysql.h"#include #include #include #pragma comment(lib,"wsock32.lib")#pragma comment(lib, "mysql_api/libmysql.lib ")//mysql参考文档#define DATA_TYPE_INT4//整型#define DATA_TYPE_CHARPTR1//char*类型#define DATA_TYPE_INVALID0//无效类型enum e_strType{e_char=0, e_cstring};namespace _TOOLS_{static CMutex g_mtxmysql;//mysql操作对象的互斥对象static CMutex g_mtxMysqlPool;//mysql连接池的互斥对象
   class CTools{public:MYSQLMysql;//mysql对象~CTools(){mysql_close( &Mysql );};CTools(){m_pResult = NULL;m_bOpen = false;};bool initmysql(const char* pIP, const char* pUser, const char* pPwd, const char* pDatabase, unsigned short nPort = 3306 );bool select_sql_beack(__in const char *pSQL, __out ...);bool select_sql_beack_s(__in const char *pSQL, __out ...);bool update_sql(__in const char *pSQL);bool insert_sql(__in const char *pSQL);bool delete_sql(__in const char *pSQL);//打断上一次执行(意思就是不支持嵌套,嵌套可以使用上面的Select)bool SelectBeack(__in const char *pSQL, e_strType, __out va_list ap);bool GetMysqlConnectStatus(){if (m_bOpen){if( mysql_ping(&Mysql)  == 0)//处于连接状态中{return true;}}return m_bOpen;}void ClearResult(){if ( m_pResult!= NULL ){mysql_free_result(m_pResult);m_pResult = NULL;m_strOldSql = "";}//m_Lastmysql.initdata();}void CloseMysql(){//if ( _pMysql ){mysql_close( &Mysql );//_pMysql = NULL;}}//是否自动提交void AutoCommitSQL(BOOL bAuto = TRUE);private:bool execute(const char* pSQL);private://MYSQL_INFO m_Lastmysql;CString m_strOldSql;//旧的SQL语句MYSQL_RES *m_pResult;//记录集bool m_bOpen;//公共接口public:static CString GetBinPath();static WCHAR* ToWChar(char *str);};class mysql_connection_pool{public:~mysql_connection_pool();//单例模式static mysql_connection_pool *GetInstance();//初始化连接size_t InitConnection(int nInitialSize=1);//设置mysql信息void SetMysqlInfo(const char* pIP,const char* pUser,const char* pPwd,const char* pDatabase,unsigned short nPort );//获取msyql操作对象CTools *GetConnection();//回收连接对象void ReleaseConnection(CTools * pObject);//销毁连接池void DestoryConnPool();protected:mysql_connection_pool();private:char m_szIP[128];char m_szUser[128];char m_szPwd[128];char m_szDatabase[128];short m_snPort;std::queue the_queue;CMutex the_mutex;};}

mysql 操作类封装 实现文件源码如下:

#include "stdafx.h"#include "tools.h"#include using namespace _TOOLS_;bool CTools::initmysql(const char* pIP, const char* pUser, const char* pPwd, const char* pDatabase, unsigned short nPort  ){//mysql初始化mysql_init(&Mysql);//连接数据库if (!mysql_real_connect(&Mysql, pIP, pUser, pPwd, pDatabase, nPort, NULL, CLIENT_MULTI_STATEMENTS)){m_bOpen = false;return m_bOpen;}mysql_query(&Mysql,"SET NAMES 'GBK'");mysql_query(&Mysql, "set global max_connections=4000");//设置最大连接数量(mysql服务器默认为151  所以这里找到配置文件 只有这个办法咯)mysql_options(&Mysql,MYSQL_READ_DEFAULT_GROUP,"IMServer");m_bOpen = true;return m_bOpen;}bool CTools::select_sql_beack(__in const char *pSQL, __out ...){va_list ap;va_start( ap, pSQL );bool bRet = SelectBeack( pSQL,e_char,ap );va_end( ap );return bRet;}bool CTools::select_sql_beack_s(__in const char *pSQL, __out ...){va_list ap;va_start( ap, pSQL );bool bRet = SelectBeack( pSQL,e_cstring,ap );va_end( ap );return bRet;}bool CTools::SelectBeack(__in const char *pSQL, e_strType nstrType, __out va_list ap){ MYSQL_ROW row;//数据MYSQL_RES *pResult = NULL;//记录集指针unsigned int num_fields;//字段个数MYSQL_FIELD* pFields;//字段类型信息if (!m_bOpen){return false;}try{if (m_strOldSql.CompareNoCase(pSQL) != 0){//没有查询过SQL新建查询ClearResult();//清理记录集数据g_mtxmysql.Lock();if(!(mysql_query(&Mysql, pSQL) == 0) ){//查询失败g_mtxmysql.Unlock();return false;}//查询数据pResult = mysql_use_result(&Mysql);g_mtxmysql.Unlock();int nCount = mysql_field_count(&Mysql);if (!pResult){return false;}m_strOldSql.Format("%s", pSQL);}else{pResult = m_pResult;}int *pnType = NULL;CString *pstrType = NULL;char * pszType = NULL;num_fields = mysql_num_fields(pResult);//获取一条数据if(!(row = mysql_fetch_row(pResult))){ClearResult();return false;}for (unsigned int i=0; itype;switch(nfieldtype){//转整型  //这里有小数点的还没有做处理 需要进一步处理case MYSQL_TYPE_SHORT:case MYSQL_TYPE_LONG:case MYSQL_TYPE_INT24:case MYSQL_TYPE_LONGLONG:case MYSQL_TYPE_FLOAT:case MYSQL_TYPE_DOUBLE:{pnType = va_arg(ap, int *);if (pnType == NULL){break;}if (row[i] == NULL){*pnType = 0;}else{*pnType = atoi(row[i]);}}break;//转字符类型case MYSQL_TYPE_DATE:case MYSQL_TYPE_TIME:case MYSQL_TYPE_DATETIME:case MYSQL_TYPE_STRING:case MYSQL_TYPE_TINY:case MYSQL_TYPE_VAR_STRING:{if (nstrType == e_cstring){pstrType = va_arg(ap,CString *);if (pstrType == NULL){break;}if (row[i] == NULL){*pstrType = "";}else{*pstrType = row[i];}}else{pszType = va_arg(ap,char *);if (pszType == NULL){break;}if (row[i] == NULL){pszType[0] = 0;}else{strcpy(pszType,row[i]);}}}break;default:{// 我未预料到的类型。把参数指针向后移;pszType = va_arg( ap, char *);}break;}}}catch (...){ClearResult();return false;}m_pResult = pResult;return true;}bool CTools::execute(const char* pSQL){ASSERT(pSQL);try{int nRet = mysql_query(&Mysql, pSQL);if ( nRet != 0 ){ const char* pError=NULL;pError = mysql_error(&Mysql);TRACE("MYSQL错误提示%s\r\n",pError);return false;}}catch (...){return false;}return true;}bool CTools::delete_sql(__in const char *pSQL){return execute(pSQL);}bool CTools::update_sql(const char *pSQL){return execute(pSQL);}bool CTools::insert_sql(const char *pSQL){return execute(pSQL);}void _TOOLS_::CTools::AutoCommitSQL(BOOL bAuto ){mysql_autocommit(&Mysql, bAuto);}CString CTools::GetBinPath(){CString sPath;GetModuleFileName(NULL, sPath.GetBufferSetLength(MAX_PATH + 1), MAX_PATH);sPath.ReleaseBuffer();int nPos;nPos = sPath.ReverseFind('\\');sPath = sPath.Left(nPos);return sPath;}WCHAR* CTools::ToWChar(char *str){static WCHAR buffer[1024];memset(buffer, 0, 1024);MultiByteToWideChar(CP_ACP, 0, str, strlen(str), buffer, 1024);return buffer;}mysql_connection_pool::mysql_connection_pool(){}mysql_connection_pool::~mysql_connection_pool(){DestoryConnPool();}mysql_connection_pool * mysql_connection_pool::GetInstance(){static mysql_connection_pool object;return &object;}CTools * mysql_connection_pool::GetConnection(){g_mtxMysqlPool.Lock();CTools *pMysqlobject = NULL;if (the_queue.empty()){g_mtxMysqlPool.Unlock();return pMysqlobject;}pMysqlobject = the_queue.front();the_queue.pop();g_mtxMysqlPool.Unlock();return pMysqlobject;}size_t _TOOLS_::mysql_connection_pool::InitConnection(int nInitialSize){ASSERT(nInitialSize > 0);g_mtxMysqlPool.Lock();for ( int i=0; iinitmysql(m_szIP, m_szUser, m_szPwd, m_szDatabase, m_snPort)){delete pObject;pObject = NULL;continue;}pObject->AutoCommitSQL(FALSE);//关闭自动调教 采用事物提交the_queue.push(pObject);}size_t nSize = the_queue.size();g_mtxMysqlPool.Unlock();return nSize;}void _TOOLS_::mysql_connection_pool::SetMysqlInfo(const char* pIP, const char* pUser, const char* pPwd, const char* pDatabase, unsigned short nPort ){ASSERT(pIP != NULL);ASSERT(pUser != NULL);ASSERT(pPwd != NULL);ASSERT(pDatabase != NULL);g_mtxMysqlPool.Lock();memcpy(m_szIP, pIP, strlen(pIP));memcpy(m_szUser, pUser, strlen(pUser));memcpy(m_szPwd, pPwd, strlen(pPwd));memcpy(m_szDatabase, pDatabase, strlen(pDatabase));m_snPort = nPort;g_mtxMysqlPool.Unlock();}void mysql_connection_pool::ReleaseConnection(CTools * pObject) {ASSERT(pObject);g_mtxMysqlPool.Lock();the_queue.push(pObject);g_mtxMysqlPool.Unlock();}void mysql_connection_pool::DestoryConnPool() {g_mtxMysqlPool.Lock();if (!the_queue.empty()){CTools *pMysqlobject = the_queue.front();the_queue.pop();pMysqlobject->insert_sql("COMMIT");delete pMysqlobject;pMysqlobject = NULL;}g_mtxMysqlPool.Unlock();}

下次在写如何使用这个类来进行mysql读写(异步读写mysql,事务处理实现批量插入数据库,连接池的使用方式)