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

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

数据库线程池

cpp 复制代码
ConnectionPool.h 文件

#ifndef CONNECTIONPOOL_H
#define CONNECTIONPOOL_H

#include <QtSql>
#include <QQueue>
#include <QString>
#include <QMutex>
#include <QMutexLocker>

#include "ConnectionPool.h"

class ConnectionPool {
public:
    static void release(); // 关闭所有的数据库连接
    static QSqlDatabase createConnection();                 // 获取数据库连接
    static void closeConnection(QSqlDatabase connection); // 释放数据库连接回连接池

    ~ConnectionPool();

private:
    static ConnectionPool& getInstance();

    ConnectionPool();
    ConnectionPool(const ConnectionPool &other);
    ConnectionPool& operator=(const ConnectionPool &other);
    QSqlDatabase createConnection(const QString &connectionName); // 创建数据库连接
    void initialize();
    void loadConfigFile();

public:

    QQueue<QString> usedConnectionNames;   // 已使用的数据库连接名
    QQueue<QString> unusedConnectionNames; // 未使用的数据库连接名

    QJsonObject mJsonObject;
    // 数据库信息
    QString hostName;
    QString databaseName;
    QString username;
    QString password;
    QString databaseType;
    int     port;

    bool    testOnBorrow;    // 取得连接的时候验证连接是否有效
    QString testOnBorrowSql; // 测试访问数据库的 SQL

    int maxWaitTime;  // 获取连接最大等待时间
    int waitInterval; // 尝试获取连接时等待间隔时间
    int maxConnectionCount; // 最大连接数



    static QMutex mutex;
    static QWaitCondition waitConnection;
    static ConnectionPool *instance;
};

#endif // CONNECTIONPOOL_H
cpp 复制代码
ConnectionPool.cpp


#include "ConnectionPool.h"
#include <QDebug>

QMutex ConnectionPool::mutex;
QWaitCondition ConnectionPool::waitConnection;
ConnectionPool* ConnectionPool::instance = NULL;

ConnectionPool::ConnectionPool()
{
    initialize();
}

ConnectionPool::~ConnectionPool()
{
    // 销毁连接池的时候删除所有的连接
    foreach(QString connectionName, usedConnectionNames)
    {
        QSqlDatabase::removeDatabase(connectionName);
    }

    foreach(QString connectionName, unusedConnectionNames)
    {
        QSqlDatabase::removeDatabase(connectionName);
    }
}

void ConnectionPool::loadConfigFile()
{
    QString path = qApp->applicationDirPath();
    QString strFile;
    strFile = path + "/config/DBConfig.json";
    QFile file(strFile);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug() << "could't open projects json";
        return;
    }

    QString value = file.readAll();
    file.close();

    QJsonParseError parseJsonErr;
    QJsonDocument document = QJsonDocument::fromJson(value.toUtf8(), &parseJsonErr);
    if(!(parseJsonErr.error == QJsonParseError::NoError))
    {
        qDebug() << parseJsonErr.errorString();
        return;
    }

    mJsonObject=document.object();
}

void ConnectionPool::initialize()
{
    //loadConfigFile();
    hostName     = "127.0.0.1";
    databaseName = "test";
    username     = "root";
    password     = "admin";
    databaseType = "QMYSQL";
    port         = 3306;
    testOnBorrow = true;
    testOnBorrowSql = "SELECT 1";
    waitInterval = 200;
    maxWaitTime     = 5000;
    maxConnectionCount = 10;

}


ConnectionPool& ConnectionPool::getInstance()
{
    if (NULL == instance)
    {
        QMutexLocker locker(&mutex);

        if (NULL == instance)
        {
            instance = new ConnectionPool();
        }
    }

    return *instance;
}

void ConnectionPool::release()
{
    QMutexLocker locker(&mutex);
    delete instance;
    instance = NULL;
}

QSqlDatabase ConnectionPool::createConnection()
{
    ConnectionPool& pool = ConnectionPool::getInstance();
    QString connectionName;

    QMutexLocker locker(&mutex);

    // 已创建连接数
    int connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();

    // 如果连接已经用完,等待 waitInterval 毫秒看看是否有可用连接,最长等待 maxWaitTime 毫秒
    for (int i = 0;
         i < pool.maxWaitTime
         && pool.unusedConnectionNames.size() == 0 && connectionCount == pool.maxConnectionCount;
         i += pool.waitInterval)
    {
        waitConnection.wait(&mutex, pool.waitInterval);

        // 重新计算已创建连接数
        connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();
    }

    qDebug() << "connectionCount:"<<connectionCount;
    qDebug() << "pool.maxConnectionCount:"<<pool.maxConnectionCount;
    if (pool.unusedConnectionNames.size() > 0)
    {
        // 有已经回收的连接,复用它们
        connectionName = pool.unusedConnectionNames.dequeue();
    }
    else if (connectionCount < pool.maxConnectionCount)
    {
        // 没有已经回收的连接,但是没有达到最大连接数,则创建新的连接
        connectionName = QString("Connection-%1").arg(connectionCount + 1);
    }
    else
    {
        // 已经达到最大连接数
        qDebug() << "Cannot create more connections.";
        return QSqlDatabase();
    }

    // 创建连接
    QSqlDatabase db = pool.createConnection(connectionName);

    // 有效的连接才放入 usedConnectionNames
    if (db.isOpen())
    {
        pool.usedConnectionNames.enqueue(connectionName);
    }

    return db;
}

void ConnectionPool::closeConnection(QSqlDatabase connection)
{
    ConnectionPool& pool = ConnectionPool::getInstance();
    QString connectionName = connection.connectionName();

    // 如果是我们创建的连接,从 used 里删除,放入 unused 里
    if (pool.usedConnectionNames.contains(connectionName))
    {
        QMutexLocker locker(&mutex);
        pool.usedConnectionNames.removeOne(connectionName);
        pool.unusedConnectionNames.enqueue(connectionName);
        waitConnection.wakeOne();
    }
}

QSqlDatabase ConnectionPool::createConnection(const QString &connectionName)
{
    // 连接已经创建过了,复用它,而不是重新创建
    if (QSqlDatabase::contains(connectionName))
    {
        QSqlDatabase db1 = QSqlDatabase::database(connectionName);

        if (testOnBorrow)
        {
            // 返回连接前访问数据库,如果连接断开,重新建立连接
            qDebug() << "Test connection on borrow, execute:" << testOnBorrowSql << ", for" << connectionName;
            QSqlQuery query(testOnBorrowSql, db1);

            if (query.lastError().type() != QSqlError::NoError && !db1.open())
            {
                qDebug() << "Open datatabase error:" << db1.lastError().text();
                return QSqlDatabase();
            }
        }

        return db1;
    }

    // 创建一个新的连接
    QSqlDatabase db = QSqlDatabase::addDatabase(databaseType, connectionName);
    db.setHostName(hostName);
    db.setDatabaseName(databaseName);
    db.setUserName(username);
    db.setPassword(password);
    db.setPort(port);
    if (!db.open())
    {
        qDebug() << "Open datatabase error:" << db.lastError().text();
        return QSqlDatabase();
    }

    return db;
}

数据库封装:

cpp 复制代码
SqlDatabase.h


#ifndef SQLDATABASE_H
#define SQLDATABASE_H

#include <QJsonArray>
#include <QJsonValue>
#include <QJsonObject>

class  SqlDatabase
{
public:
    SqlDatabase();
    ~SqlDatabase();

public:
    static void InsertDB(QString strTableName,QJsonArray jsonValue);
    static void UpdateDB(QString strTableName,QJsonArray jsonValue,QString strColumnCondition);
    static int  InsertDB(QString strTableName,QJsonObject jsonValue);
    static void UpdateDB(QString strTableName,QJsonObject jsonValue,QString strCondition);
    static void QueryRecord(QString strSql,QJsonArray &nJsonValue);
    static int  QueryCount(QString strSql);
    static bool Delete(QString strSql);
    static bool Delete(QString strTableName,QString strCondition);
};

#endif // SQLDATABASE_H
cpp 复制代码
SqlDatabase.cpp



#include "SqlDatabase.h"
#include "ConnectionPool.h"
#include <QDebug>


#pragma execution_character_set("utf-8")

SqlDatabase::SqlDatabase()
{

}

SqlDatabase::~SqlDatabase()
{
    ConnectionPool::Destroy();
}

void SqlDatabase::InsertDB(QString strTableName,QJsonArray jsonValues)
{
    QSqlDatabase db =ConnectionPool::CreateConnection();
    QString strValues="";
    QString strNames="";
    bool iskeyName=false;
    for(int j=0;j<jsonValues.size();j++)
    {
        QJsonObject::iterator it;
        QString strKeyValue;
        QJsonObject tmpObj =jsonValues.at(j).toObject();
        for(it=tmpObj.begin();it!=tmpObj.end();it++)
        {
            if(strKeyValue.isEmpty())
            {
                if(it.value().isDouble())
                {
                    it.value()=QString::number(it.value().toDouble(),'f',12);
                }
                strKeyValue=QString("'%1'").arg(it.value().toString());
                if(!iskeyName)
                {
                    strNames=QString("%1").arg(it.key());
                }
            }
            else
            {
                if(it.value().isDouble())
                {
                    it.value()=QString::number(it.value().toDouble(),'f',12);
                }
                strKeyValue+=QString(",'%1'").arg(it.value().toString());
                if(!iskeyName)
                {
                    strNames+=QString(",%1").arg(it.key());
                }
            }
        }

        iskeyName =true;
        if(strValues.isEmpty())
        {
            strValues +="("+strKeyValue+")";
        }
        else
        {
            strValues +=",("+strKeyValue+")";
        }
    }
    QString strSql=QString("INSERT INTO %1 (%2)  VALUES %3 ").arg(strTableName).arg(strNames).arg(strValues);
    QSqlQuery query(db);
    if(!query.exec(strSql))
    {
        qDebug()<<"Failed to INSERT:"<<strSql;
    }
    ConnectionPool::CloseConnection(db);
}

void SqlDatabase::UpdateDB(QString strTableName,QJsonArray jsonValue,QString strColumnCondition)
{
	QString mHeadSql= QString(" UPDATE  %1 m,( ").arg(strTableName);
    QString mEndSql=" ) n ";
	QString mSetConditionSql="";
    QString mValueSql="";
    QString mCondition="";
    QString strSql="";
	for(int i=0;i<jsonValue.size();i++)
    {
        QJsonObject jsonObject=jsonValue.at(i).toObject();
        QJsonObject::iterator it;
        QString strValue="";
        if(!mValueSql.isEmpty())
        {
            mValueSql +=  " UNION ";
        }
        for(it=jsonObject.begin();it!=jsonObject.end();it++)
        {
            if(it.value().isDouble())
            {
                it.value()=QString::number(it.value().toDouble(),'f',3);
            }
            if(strValue =="")
			{
                strValue =QString(" SELECT '%0' as `%1`").arg(it.value().toString()).arg(it.key());
                mSetConditionSql =QString(" SET m.%0 = n.%1").arg(it.key()).arg(it.key());
			}
			else
			{
                strValue +=QString(",'%0' as `%1`").arg(it.value().toString()).arg(it.key());
                mSetConditionSql += QString(" ,m.%0 = n.%1").arg(it.key()).arg(it.key());
			}	
		}

        mValueSql += strValue;
	}

    mCondition += QString(" WHERE m.%0 = n.%1").arg(strColumnCondition).arg(strColumnCondition);

    strSql =mHeadSql +mValueSql + mEndSql + mSetConditionSql+ mCondition;
    qDebug()<<strSql;
}

int SqlDatabase::InsertDB(QString strTableName,QJsonObject jsonValue)
{
    QSqlDatabase db =ConnectionPool::CreateConnection();
    QString strValues="";
    QString strNames="";
    int nLastNum=0;
    QJsonObject::iterator it;
    for(it=jsonValue.begin();it!=jsonValue.end();it++)
    {
        if(strValues.isEmpty())
        {
            if(it.value().isDouble())
            {
                it.value()=QString::number(it.value().toDouble(),'f',12);
            }
            strValues=QString("'%1'").arg(it.value().toString());
            strNames=QString("%1").arg(it.key());
        }
        else
        {
            if(it.value().isDouble())
            {
                it.value()=QString::number(it.value().toDouble(),'f',12);
            }
            strValues+=QString(",'%1'").arg(it.value().toString());
            strNames+=QString(",%1").arg(it.key());
        }
    }
    QString strSql=QString("INSERT INTO %1 (%2)  VALUES(%3) ").arg(strTableName).arg(strNames).arg(strValues);

    QSqlQuery query(db);
    if(!query.exec(strSql))
    {
        qDebug()<<"Failed to InsertDB:"<<query.lastError().text();
    }
    else
    {
        nLastNum=query.lastInsertId().toInt();
    }

    ConnectionPool::CloseConnection(db);
    return  nLastNum;
}

void SqlDatabase::UpdateDB(QString strTableName,QJsonObject jsonValue,QString strCondition)
{
    QSqlDatabase db =ConnectionPool::CreateConnection();
    QString strValues="";
    QString strNames="";
    QJsonObject::iterator it;
    for(it=jsonValue.begin();it!=jsonValue.end();it++)
    {
        if(strValues.isEmpty())
        {
            if(it.value().isDouble())
            {
                it.value()=QString::number(it.value().toDouble(),'f',12);
            }
            strValues=QString("%1='%2'").arg(it.key()).arg(it.value().toString());
        }
        else
        {
            if(it.value().isDouble())
            {
                it.value()=QString::number(it.value().toDouble(),'f',12);
            }
            strValues+=QString(",%1='%2'").arg(it.key()).arg(it.value().toString());
        }
    }

    QString strSql=QString("UPDATE  %1  SET %2  %3 ").arg(strTableName).arg(strValues).arg(strCondition);
    QSqlQuery query(db);
    if(!query.exec(strSql))
    {
        qDebug()<<"Failed to UpdateDB:"<<query.lastError().text();
    }

    ConnectionPool::CloseConnection(db);
}

void SqlDatabase::QueryRecord(QString strSql,QJsonArray &nJsonValue)
{
    QSqlDatabase db =ConnectionPool::CreateConnection();
    QSqlQuery query(db);
    if(!query.exec(strSql))
    {
       qDebug()<<"Failed to QueryRecord:"<<query.lastError().text();
    }

    while(query.next())
    {
        QSqlRecord qResultRecord=query.record();
        QJsonObject jsonObject;
        for(int fileIndex =0; fileIndex<qResultRecord.count();fileIndex++)
        {
            if(query.value(fileIndex).isNull())
            {
                jsonObject.insert(qResultRecord.fieldName(fileIndex),QJsonValue::Null);
            }
            else if(query.value(fileIndex).type() ==QVariant::Int)
            {
                jsonObject.insert(qResultRecord.fieldName(fileIndex),query.value(fileIndex).toInt());
            }
            else if(query.value(fileIndex).type() == QVariant::Double)
            {
                jsonObject.insert(qResultRecord.fieldName(fileIndex),query.value(fileIndex).toDouble());
            }
            else if(query.value(fileIndex).type() == QVariant::LongLong)
            {
                jsonObject.insert(qResultRecord.fieldName(fileIndex),query.value(fileIndex).toLongLong());
            }
            else
            {
                jsonObject.insert(qResultRecord.fieldName(fileIndex),query.value(fileIndex).toString());
            }
        }
        nJsonValue.append(jsonObject);
    }
    ConnectionPool::CloseConnection(db);
}

int SqlDatabase::QueryCount(QString strSql)
{
   QSqlDatabase db =ConnectionPool::CreateConnection();
   QSqlQuery query(db);
   int totalCnt=0;
   QString strSqlCount=QString(" SELECT COUNT(*) AS Cnt FROM  (%1) t ").arg(strSql);
   if(!query.exec(strSqlCount))
   {
       qDebug()<<"Failed to QueryCount:"<<query.lastError().text();
   }

   while(query.next())
   {
        totalCnt=query.value("Cnt").toInt();
   }
   ConnectionPool::CloseConnection(db);
   return totalCnt;
}

bool SqlDatabase::Delete(QString strSql)
{
    bool bRet =true;
    QSqlDatabase db =ConnectionPool::CreateConnection();
    QSqlQuery query(db);
    if(!query.exec(strSql))
    {
        qDebug()<<"Failed to Delete:"<<query.lastError().text();
        bRet = false;
    }

    ConnectionPool::CloseConnection(db);
    return bRet;
}

bool SqlDatabase::Delete(QString strTableName,QString strCondition)
{
    bool bRet =true;
    QSqlDatabase db =ConnectionPool::CreateConnection();
    QSqlQuery query(db);
    QString strSql=QString(" DELETE FROM %1 %2 ").arg(strTableName).arg(strCondition);
    if(!query.exec(strSql))
    {
        qDebug()<<"Failed to Delete:"<<query.lastError().text();
        bRet = false;
    }

    ConnectionPool::CloseConnection(db);
    return bRet;
}

此处说一下批量更新

源数据是这样需要更新

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 语句 批量更新

sql 复制代码
UPDATE test m,(
	SELECT
		'1.000' AS `id`,
		'a' AS `name`,
		'22.000' AS `ranking`,
		'56.900' AS `score1`,
		'39.500' AS `score2`,
		'56.700' AS `score3`,
		'aaaa' AS `shorName` UNION
	SELECT
		'2.000' AS `id`,
		'b' AS `name`,
		'27.000' AS `ranking`,
		'89.900' AS `score1`,
		'39.500' AS `score2`,
		'59.900' AS `score3`,
		'bbbbb' AS `shorName` UNION
	SELECT
		'3.000' AS `id`,
		'c' AS `name`,
		'29.000' AS `ranking`,
		'76.900' AS `score1`,
		'72.900' AS `score2`,
		'81.900' AS `score3`,
		'ccccc' AS `shorName` 
	) n 
	SET m.id = n.id,
	m.NAME = n.NAME,
	m.ranking = n.ranking,
	m.score1 = n.score1,
	m.score2 = n.score2,
	m.score3 = n.score3,
	m.shorName = n.shorName 
WHERE
	m.id = n.id
相关推荐
siriuuus几秒前
MySQL 数据备份
数据库·mysql·备份
姚远Oracle ACE几秒前
Oracle AWR 报告中的SQL来自哪儿?
数据库·sql·oracle
熊文豪4 分钟前
KingbaseES数据库性能调优工具全面解析
数据库·kingbasees·金仓数据库·电科金仓
Han.miracle9 分钟前
Java线程的学习—多线程(一)
java·开发语言·学习
冠希陈、19 分钟前
PHP7.4.33 安装sqlsrv扩展
数据库
光影341524 分钟前
专利撰写与申请核心要点简报
前端·数据库·php
应用市场24 分钟前
PHP microtime()函数精度问题深度解析与解决方案
android·开发语言·php
长存祈月心40 分钟前
Rust HashSet 与 BTreeSet深度剖析
开发语言·后端·rust
长存祈月心44 分钟前
Rust BTreeMap 红黑树
开发语言·后端·rust
心灵宝贝1 小时前
申威ky10架构安装MongoDB 4.0.1(rpm包:mongodb-4.0.1-8.ky10.sw_64.rpm)详细步骤
数据库·mongodb·架构