• QT mysql 数据库线程池 与数据库操作封装


    最近事情比较多很久没有写学习笔记了,数据库线程池,+ 数据库封装,虽说数据库操作有很多不需要写sql 的,ORM 封装的方式去操作数据库。但是从业这些年一直是自己动手写sql ,还是改不了这个习惯。不说了直接上代码。

    数据库线程池

    1. ConnectionPool.h 文件
    2. #ifndef CONNECTIONPOOL_H
    3. #define CONNECTIONPOOL_H
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "ConnectionPool.h"
    10. class ConnectionPool {
    11. public:
    12. static void release(); // 关闭所有的数据库连接
    13. static QSqlDatabase createConnection(); // 获取数据库连接
    14. static void closeConnection(QSqlDatabase connection); // 释放数据库连接回连接池
    15. ~ConnectionPool();
    16. private:
    17. static ConnectionPool& getInstance();
    18. ConnectionPool();
    19. ConnectionPool(const ConnectionPool &other);
    20. ConnectionPool& operator=(const ConnectionPool &other);
    21. QSqlDatabase createConnection(const QString &connectionName); // 创建数据库连接
    22. void initialize();
    23. void loadConfigFile();
    24. public:
    25. QQueue usedConnectionNames; // 已使用的数据库连接名
    26. QQueue unusedConnectionNames; // 未使用的数据库连接名
    27. QJsonObject mJsonObject;
    28. // 数据库信息
    29. QString hostName;
    30. QString databaseName;
    31. QString username;
    32. QString password;
    33. QString databaseType;
    34. int port;
    35. bool testOnBorrow; // 取得连接的时候验证连接是否有效
    36. QString testOnBorrowSql; // 测试访问数据库的 SQL
    37. int maxWaitTime; // 获取连接最大等待时间
    38. int waitInterval; // 尝试获取连接时等待间隔时间
    39. int maxConnectionCount; // 最大连接数
    40. static QMutex mutex;
    41. static QWaitCondition waitConnection;
    42. static ConnectionPool *instance;
    43. };
    44. #endif // CONNECTIONPOOL_H
    1. ConnectionPool.cpp
    2. #include "ConnectionPool.h"
    3. #include
    4. QMutex ConnectionPool::mutex;
    5. QWaitCondition ConnectionPool::waitConnection;
    6. ConnectionPool* ConnectionPool::instance = NULL;
    7. ConnectionPool::ConnectionPool()
    8. {
    9. initialize();
    10. }
    11. ConnectionPool::~ConnectionPool()
    12. {
    13. // 销毁连接池的时候删除所有的连接
    14. foreach(QString connectionName, usedConnectionNames)
    15. {
    16. QSqlDatabase::removeDatabase(connectionName);
    17. }
    18. foreach(QString connectionName, unusedConnectionNames)
    19. {
    20. QSqlDatabase::removeDatabase(connectionName);
    21. }
    22. }
    23. void ConnectionPool::loadConfigFile()
    24. {
    25. QString path = qApp->applicationDirPath();
    26. QString strFile;
    27. strFile = path + "/config/DBConfig.json";
    28. QFile file(strFile);
    29. if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    30. {
    31. qDebug() << "could't open projects json";
    32. return;
    33. }
    34. QString value = file.readAll();
    35. file.close();
    36. QJsonParseError parseJsonErr;
    37. QJsonDocument document = QJsonDocument::fromJson(value.toUtf8(), &parseJsonErr);
    38. if(!(parseJsonErr.error == QJsonParseError::NoError))
    39. {
    40. qDebug() << parseJsonErr.errorString();
    41. return;
    42. }
    43. mJsonObject=document.object();
    44. }
    45. void ConnectionPool::initialize()
    46. {
    47. //loadConfigFile();
    48. hostName = "127.0.0.1";
    49. databaseName = "test";
    50. username = "root";
    51. password = "admin";
    52. databaseType = "QMYSQL";
    53. port = 3306;
    54. testOnBorrow = true;
    55. testOnBorrowSql = "SELECT 1";
    56. waitInterval = 200;
    57. maxWaitTime = 5000;
    58. maxConnectionCount = 10;
    59. }
    60. ConnectionPool& ConnectionPool::getInstance()
    61. {
    62. if (NULL == instance)
    63. {
    64. QMutexLocker locker(&mutex);
    65. if (NULL == instance)
    66. {
    67. instance = new ConnectionPool();
    68. }
    69. }
    70. return *instance;
    71. }
    72. void ConnectionPool::release()
    73. {
    74. QMutexLocker locker(&mutex);
    75. delete instance;
    76. instance = NULL;
    77. }
    78. QSqlDatabase ConnectionPool::createConnection()
    79. {
    80. ConnectionPool& pool = ConnectionPool::getInstance();
    81. QString connectionName;
    82. QMutexLocker locker(&mutex);
    83. // 已创建连接数
    84. int connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();
    85. // 如果连接已经用完,等待 waitInterval 毫秒看看是否有可用连接,最长等待 maxWaitTime 毫秒
    86. for (int i = 0;
    87. i < pool.maxWaitTime
    88. && pool.unusedConnectionNames.size() == 0 && connectionCount == pool.maxConnectionCount;
    89. i += pool.waitInterval)
    90. {
    91. waitConnection.wait(&mutex, pool.waitInterval);
    92. // 重新计算已创建连接数
    93. connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();
    94. }
    95. qDebug() << "connectionCount:"<
    96. qDebug() << "pool.maxConnectionCount:"<
    97. if (pool.unusedConnectionNames.size() > 0)
    98. {
    99. // 有已经回收的连接,复用它们
    100. connectionName = pool.unusedConnectionNames.dequeue();
    101. }
    102. else if (connectionCount < pool.maxConnectionCount)
    103. {
    104. // 没有已经回收的连接,但是没有达到最大连接数,则创建新的连接
    105. connectionName = QString("Connection-%1").arg(connectionCount + 1);
    106. }
    107. else
    108. {
    109. // 已经达到最大连接数
    110. qDebug() << "Cannot create more connections.";
    111. return QSqlDatabase();
    112. }
    113. // 创建连接
    114. QSqlDatabase db = pool.createConnection(connectionName);
    115. // 有效的连接才放入 usedConnectionNames
    116. if (db.isOpen())
    117. {
    118. pool.usedConnectionNames.enqueue(connectionName);
    119. }
    120. return db;
    121. }
    122. void ConnectionPool::closeConnection(QSqlDatabase connection)
    123. {
    124. ConnectionPool& pool = ConnectionPool::getInstance();
    125. QString connectionName = connection.connectionName();
    126. // 如果是我们创建的连接,从 used 里删除,放入 unused 里
    127. if (pool.usedConnectionNames.contains(connectionName))
    128. {
    129. QMutexLocker locker(&mutex);
    130. pool.usedConnectionNames.removeOne(connectionName);
    131. pool.unusedConnectionNames.enqueue(connectionName);
    132. waitConnection.wakeOne();
    133. }
    134. }
    135. QSqlDatabase ConnectionPool::createConnection(const QString &connectionName)
    136. {
    137. // 连接已经创建过了,复用它,而不是重新创建
    138. if (QSqlDatabase::contains(connectionName))
    139. {
    140. QSqlDatabase db1 = QSqlDatabase::database(connectionName);
    141. if (testOnBorrow)
    142. {
    143. // 返回连接前访问数据库,如果连接断开,重新建立连接
    144. qDebug() << "Test connection on borrow, execute:" << testOnBorrowSql << ", for" << connectionName;
    145. QSqlQuery query(testOnBorrowSql, db1);
    146. if (query.lastError().type() != QSqlError::NoError && !db1.open())
    147. {
    148. qDebug() << "Open datatabase error:" << db1.lastError().text();
    149. return QSqlDatabase();
    150. }
    151. }
    152. return db1;
    153. }
    154. // 创建一个新的连接
    155. QSqlDatabase db = QSqlDatabase::addDatabase(databaseType, connectionName);
    156. db.setHostName(hostName);
    157. db.setDatabaseName(databaseName);
    158. db.setUserName(username);
    159. db.setPassword(password);
    160. db.setPort(port);
    161. if (!db.open())
    162. {
    163. qDebug() << "Open datatabase error:" << db.lastError().text();
    164. return QSqlDatabase();
    165. }
    166. return db;
    167. }

    数据库封装:

    1. SqlDatabase.h
    2. #ifndef SQLDATABASE_H
    3. #define SQLDATABASE_H
    4. #include
    5. #include
    6. #include
    7. class SqlDatabase
    8. {
    9. public:
    10. SqlDatabase();
    11. ~SqlDatabase();
    12. public:
    13. static void InsertDB(QString strTableName,QJsonArray jsonValue);
    14. static void UpdateDB(QString strTableName,QJsonArray jsonValue,QString strColumnCondition);
    15. static int InsertDB(QString strTableName,QJsonObject jsonValue);
    16. static void UpdateDB(QString strTableName,QJsonObject jsonValue,QString strCondition);
    17. static void QueryRecord(QString strSql,QJsonArray &nJsonValue);
    18. static int QueryCount(QString strSql);
    19. static bool Delete(QString strSql);
    20. static bool Delete(QString strTableName,QString strCondition);
    21. };
    22. #endif // SQLDATABASE_H

     

    1. SqlDatabase.cpp
    2. #include "SqlDatabase.h"
    3. #include "ConnectionPool.h"
    4. #include
    5. #pragma execution_character_set("utf-8")
    6. SqlDatabase::SqlDatabase()
    7. {
    8. }
    9. SqlDatabase::~SqlDatabase()
    10. {
    11. ConnectionPool::Destroy();
    12. }
    13. void SqlDatabase::InsertDB(QString strTableName,QJsonArray jsonValues)
    14. {
    15. QSqlDatabase db =ConnectionPool::CreateConnection();
    16. QString strValues="";
    17. QString strNames="";
    18. bool iskeyName=false;
    19. for(int j=0;jsize();j++)
    20. {
    21. QJsonObject::iterator it;
    22. QString strKeyValue;
    23. QJsonObject tmpObj =jsonValues.at(j).toObject();
    24. for(it=tmpObj.begin();it!=tmpObj.end();it++)
    25. {
    26. if(strKeyValue.isEmpty())
    27. {
    28. if(it.value().isDouble())
    29. {
    30. it.value()=QString::number(it.value().toDouble(),'f',12);
    31. }
    32. strKeyValue=QString("'%1'").arg(it.value().toString());
    33. if(!iskeyName)
    34. {
    35. strNames=QString("%1").arg(it.key());
    36. }
    37. }
    38. else
    39. {
    40. if(it.value().isDouble())
    41. {
    42. it.value()=QString::number(it.value().toDouble(),'f',12);
    43. }
    44. strKeyValue+=QString(",'%1'").arg(it.value().toString());
    45. if(!iskeyName)
    46. {
    47. strNames+=QString(",%1").arg(it.key());
    48. }
    49. }
    50. }
    51. iskeyName =true;
    52. if(strValues.isEmpty())
    53. {
    54. strValues +="("+strKeyValue+")";
    55. }
    56. else
    57. {
    58. strValues +=",("+strKeyValue+")";
    59. }
    60. }
    61. QString strSql=QString("INSERT INTO %1 (%2) VALUES %3 ").arg(strTableName).arg(strNames).arg(strValues);
    62. QSqlQuery query(db);
    63. if(!query.exec(strSql))
    64. {
    65. qDebug()<<"Failed to INSERT:"<
    66. }
    67. ConnectionPool::CloseConnection(db);
    68. }
    69. void SqlDatabase::UpdateDB(QString strTableName,QJsonArray jsonValue,QString strColumnCondition)
    70. {
    71. QString mHeadSql= QString(" UPDATE %1 m,( ").arg(strTableName);
    72. QString mEndSql=" ) n ";
    73. QString mSetConditionSql="";
    74. QString mValueSql="";
    75. QString mCondition="";
    76. QString strSql="";
    77. for(int i=0;isize();i++)
    78. {
    79. QJsonObject jsonObject=jsonValue.at(i).toObject();
    80. QJsonObject::iterator it;
    81. QString strValue="";
    82. if(!mValueSql.isEmpty())
    83. {
    84. mValueSql += " UNION ";
    85. }
    86. for(it=jsonObject.begin();it!=jsonObject.end();it++)
    87. {
    88. if(it.value().isDouble())
    89. {
    90. it.value()=QString::number(it.value().toDouble(),'f',3);
    91. }
    92. if(strValue =="")
    93. {
    94. strValue =QString(" SELECT '%0' as `%1`").arg(it.value().toString()).arg(it.key());
    95. mSetConditionSql =QString(" SET m.%0 = n.%1").arg(it.key()).arg(it.key());
    96. }
    97. else
    98. {
    99. strValue +=QString(",'%0' as `%1`").arg(it.value().toString()).arg(it.key());
    100. mSetConditionSql += QString(" ,m.%0 = n.%1").arg(it.key()).arg(it.key());
    101. }
    102. }
    103. mValueSql += strValue;
    104. }
    105. mCondition += QString(" WHERE m.%0 = n.%1").arg(strColumnCondition).arg(strColumnCondition);
    106. strSql =mHeadSql +mValueSql + mEndSql + mSetConditionSql+ mCondition;
    107. qDebug()<
    108. }
    109. int SqlDatabase::InsertDB(QString strTableName,QJsonObject jsonValue)
    110. {
    111. QSqlDatabase db =ConnectionPool::CreateConnection();
    112. QString strValues="";
    113. QString strNames="";
    114. int nLastNum=0;
    115. QJsonObject::iterator it;
    116. for(it=jsonValue.begin();it!=jsonValue.end();it++)
    117. {
    118. if(strValues.isEmpty())
    119. {
    120. if(it.value().isDouble())
    121. {
    122. it.value()=QString::number(it.value().toDouble(),'f',12);
    123. }
    124. strValues=QString("'%1'").arg(it.value().toString());
    125. strNames=QString("%1").arg(it.key());
    126. }
    127. else
    128. {
    129. if(it.value().isDouble())
    130. {
    131. it.value()=QString::number(it.value().toDouble(),'f',12);
    132. }
    133. strValues+=QString(",'%1'").arg(it.value().toString());
    134. strNames+=QString(",%1").arg(it.key());
    135. }
    136. }
    137. QString strSql=QString("INSERT INTO %1 (%2) VALUES(%3) ").arg(strTableName).arg(strNames).arg(strValues);
    138. QSqlQuery query(db);
    139. if(!query.exec(strSql))
    140. {
    141. qDebug()<<"Failed to InsertDB:"<lastError().text();
    142. }
    143. else
    144. {
    145. nLastNum=query.lastInsertId().toInt();
    146. }
    147. ConnectionPool::CloseConnection(db);
    148. return nLastNum;
    149. }
    150. void SqlDatabase::UpdateDB(QString strTableName,QJsonObject jsonValue,QString strCondition)
    151. {
    152. QSqlDatabase db =ConnectionPool::CreateConnection();
    153. QString strValues="";
    154. QString strNames="";
    155. QJsonObject::iterator it;
    156. for(it=jsonValue.begin();it!=jsonValue.end();it++)
    157. {
    158. if(strValues.isEmpty())
    159. {
    160. if(it.value().isDouble())
    161. {
    162. it.value()=QString::number(it.value().toDouble(),'f',12);
    163. }
    164. strValues=QString("%1='%2'").arg(it.key()).arg(it.value().toString());
    165. }
    166. else
    167. {
    168. if(it.value().isDouble())
    169. {
    170. it.value()=QString::number(it.value().toDouble(),'f',12);
    171. }
    172. strValues+=QString(",%1='%2'").arg(it.key()).arg(it.value().toString());
    173. }
    174. }
    175. QString strSql=QString("UPDATE %1 SET %2 %3 ").arg(strTableName).arg(strValues).arg(strCondition);
    176. QSqlQuery query(db);
    177. if(!query.exec(strSql))
    178. {
    179. qDebug()<<"Failed to UpdateDB:"<lastError().text();
    180. }
    181. ConnectionPool::CloseConnection(db);
    182. }
    183. void SqlDatabase::QueryRecord(QString strSql,QJsonArray &nJsonValue)
    184. {
    185. QSqlDatabase db =ConnectionPool::CreateConnection();
    186. QSqlQuery query(db);
    187. if(!query.exec(strSql))
    188. {
    189. qDebug()<<"Failed to QueryRecord:"<lastError().text();
    190. }
    191. while(query.next())
    192. {
    193. QSqlRecord qResultRecord=query.record();
    194. QJsonObject jsonObject;
    195. for(int fileIndex =0; fileIndexcount();fileIndex++)
    196. {
    197. if(query.value(fileIndex).isNull())
    198. {
    199. jsonObject.insert(qResultRecord.fieldName(fileIndex),QJsonValue::Null);
    200. }
    201. else if(query.value(fileIndex).type() ==QVariant::Int)
    202. {
    203. jsonObject.insert(qResultRecord.fieldName(fileIndex),query.value(fileIndex).toInt());
    204. }
    205. else if(query.value(fileIndex).type() == QVariant::Double)
    206. {
    207. jsonObject.insert(qResultRecord.fieldName(fileIndex),query.value(fileIndex).toDouble());
    208. }
    209. else if(query.value(fileIndex).type() == QVariant::LongLong)
    210. {
    211. jsonObject.insert(qResultRecord.fieldName(fileIndex),query.value(fileIndex).toLongLong());
    212. }
    213. else
    214. {
    215. jsonObject.insert(qResultRecord.fieldName(fileIndex),query.value(fileIndex).toString());
    216. }
    217. }
    218. nJsonValue.append(jsonObject);
    219. }
    220. ConnectionPool::CloseConnection(db);
    221. }
    222. int SqlDatabase::QueryCount(QString strSql)
    223. {
    224. QSqlDatabase db =ConnectionPool::CreateConnection();
    225. QSqlQuery query(db);
    226. int totalCnt=0;
    227. QString strSqlCount=QString(" SELECT COUNT(*) AS Cnt FROM (%1) t ").arg(strSql);
    228. if(!query.exec(strSqlCount))
    229. {
    230. qDebug()<<"Failed to QueryCount:"<lastError().text();
    231. }
    232. while(query.next())
    233. {
    234. totalCnt=query.value("Cnt").toInt();
    235. }
    236. ConnectionPool::CloseConnection(db);
    237. return totalCnt;
    238. }
    239. bool SqlDatabase::Delete(QString strSql)
    240. {
    241. bool bRet =true;
    242. QSqlDatabase db =ConnectionPool::CreateConnection();
    243. QSqlQuery query(db);
    244. if(!query.exec(strSql))
    245. {
    246. qDebug()<<"Failed to Delete:"<lastError().text();
    247. bRet = false;
    248. }
    249. ConnectionPool::CloseConnection(db);
    250. return bRet;
    251. }
    252. bool SqlDatabase::Delete(QString strTableName,QString strCondition)
    253. {
    254. bool bRet =true;
    255. QSqlDatabase db =ConnectionPool::CreateConnection();
    256. QSqlQuery query(db);
    257. QString strSql=QString(" DELETE FROM %1 %2 ").arg(strTableName).arg(strCondition);
    258. if(!query.exec(strSql))
    259. {
    260. qDebug()<<"Failed to Delete:"<lastError().text();
    261. bRet = false;
    262. }
    263. ConnectionPool::CloseConnection(db);
    264. return bRet;
    265. }

    此处说一下批量更新

    源数据是这样需要更新

    id:1      shorName  :aaaaa       score1:56.9   ranking  :22

    id:2      shorName  :bbbbb       score1:89.9  score3:59.9  ranking  :27

    id:3      shorName  :ccccc       score1:76.9   score2:81.9  ranking  :29

    sql 语句 批量更新

    1. UPDATE test m,(
    2. SELECT
    3. '1.000' AS `id`,
    4. 'a' AS `name`,
    5. '22.000' AS `ranking`,
    6. '56.900' AS `score1`,
    7. '39.500' AS `score2`,
    8. '56.700' AS `score3`,
    9. 'aaaa' AS `shorName` UNION
    10. SELECT
    11. '2.000' AS `id`,
    12. 'b' AS `name`,
    13. '27.000' AS `ranking`,
    14. '89.900' AS `score1`,
    15. '39.500' AS `score2`,
    16. '59.900' AS `score3`,
    17. 'bbbbb' AS `shorName` UNION
    18. SELECT
    19. '3.000' AS `id`,
    20. 'c' AS `name`,
    21. '29.000' AS `ranking`,
    22. '76.900' AS `score1`,
    23. '72.900' AS `score2`,
    24. '81.900' AS `score3`,
    25. 'ccccc' AS `shorName`
    26. ) n
    27. SET m.id = n.id,
    28. m.NAME = n.NAME,
    29. m.ranking = n.ranking,
    30. m.score1 = n.score1,
    31. m.score2 = n.score2,
    32. m.score3 = n.score3,
    33. m.shorName = n.shorName
    34. WHERE
    35. m.id = n.id

  • 相关阅读:
    cap分布式理论
    idea一键打包docker镜像并推送远程harbor仓库的方法(包含spotify和fabric8两种方法)--全网唯一正确,秒杀99%水文
    Java.lang.Character类中isLetter()方法具有什么功能呢?
    OpenCV 颜色检测| color detection
    Spring AI 接入OpenAI实现文字生成图片功能
    HTML+CSS+JS网页设计期末课程大作业——上海旅游景点(10页)web前端开发技术 web课程设计 网页规划与设计
    干货 | RDBMS 索引类型概述
    【每日一题】线段重叠
    文件管理工具“三剑客” #Everything #SpaceSniffer #Clover
    DAIR-V2X-V 3D检测数据集 转为Kitti格式 | 可视化
  • 原文地址:https://blog.csdn.net/windows_oracle/article/details/127325522