QT数据库连接管理类

使用单例管理整个项目的数据库连接。

在QT中不同线程须使用不同的数据库实例。

MySql有连接超时——超过设定(默认8小时)没有活动会关闭连接。

一、头文件

#pragma once
#ifndef CSQLDATABASE_H
#define CSQLDATABASE_H

#include <QtSql>
#include <QString>
#include <QMutex>
#include <QMutexLocker>
#include <QWaitCondition>
#include <QQueue>
#include <QList>
#include <QSet>
#include <QVariant>

class CSQLDatabase;
typedef std::shared_ptr<CSQLDatabase> CSQLDatabasePtr;


class CSQLDatabase
{
public:
    /*
     * 单例模式获取
     * 参数:ip,用户名,用户密码,数据库名,数据库类型,端口号
     */
    static CSQLDatabase* GetInstance();
    //参数设置,仅执行一次
    void                initParas(QString qsHostName, QString qsUser, QString qsPassWd,
        QString qsDatabase, QString qsDatabaseType, int nPort
        );
    bool                ExecuteStmt(QString qsSql); //用于增删改
    bool                ExecuteStmt(QString qsSql,QList<QVariant> bindList); //用于增删改
    QSqlQuery           ExecuteQuery(QString qsSql);//用于查询
    QSqlQuery           ExecuteQuery(QString qsSql, QList<QVariant> bindList);//用于查询

    ~CSQLDatabase();

private:
    CSQLDatabase();

    QSqlDatabase    OpenConnection();
    //void            CloseConnection(QSqlDatabase connection);
    QSqlDatabase    CreateConnect(const QString& qsConnName);

    bool            IsOpen(QSqlDatabase db);

    class GC
    {
    public:
        ~GC()
        {
            // 可以在这里销毁所有的资源,例如:db 连接、文件句柄等
            if (m_pInstance) {
                //std::cout << "Here destroy the m_pSingleton..." << endl;
                delete m_pInstance;
                m_pInstance = nullptr;
            }
        }
        static GC gc;  // 用于释放单例
    };
private:
    int m_nPort;

    QString m_qsHostName;
    QString m_qsUser;
    QString m_qsPassWd;
    QString m_qsDatabase;
    QString m_qsDatabaseType;



    QSet<QString> m_setThreadConnNames;


    static QMutex m_Mutex;
    static CSQLDatabase* m_pInstance;
};

#endif // CSQLDATABASE_H

二、CPP

#include "CSQLDatabase.h"
#include <QThread>
//初始化静态变量
QMutex CSQLDatabase::m_Mutex;
CSQLDatabase* CSQLDatabase::m_pInstance = nullptr;
CSQLDatabase::GC CSQLDatabase::GC::gc; // 重要


CSQLDatabase* CSQLDatabase::GetInstance()
{
    //双重检测加锁
    if (!m_pInstance) {
        QMutexLocker locker(&m_Mutex);
        if (!m_pInstance)
            m_pInstance= new CSQLDatabase();
    }
    return m_pInstance;
}

CSQLDatabase::CSQLDatabase()    
{
}

CSQLDatabase::~CSQLDatabase()
{
    QMutexLocker locker(&m_Mutex);    
    for (auto s : m_setThreadConnNames) {
        QSqlDatabase::removeDatabase(s);
    }
    
    m_pInstance = nullptr;
}

QSqlDatabase CSQLDatabase::OpenConnection()
{
    QMutexLocker locker(&m_Mutex);
    quint32 nThread =(quint32) QThread::currentThread();
    QString qsConnName=QString("Connection-Thread-%1").arg((qint32)QThread::currentThread());
    qDebug() << qsConnName << " OpenConnection()  " << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    

    if (!m_setThreadConnNames.contains(qsConnName)) {
        m_setThreadConnNames.insert(qsConnName);
    }
    QSqlDatabase db = CreateConnect(qsConnName);

    return db;
}

//void CSQLDatabase::CloseConnection(QSqlDatabase connection)
//{
//    //关闭连接
//}

QSqlDatabase CSQLDatabase::CreateConnect(const QString &qsConnName)
{
    //查看该连接名是否已经创建过连接
    if (QSqlDatabase::contains(qsConnName))
    {
        QSqlDatabase db = QSqlDatabase::database(qsConnName);
        return db;
    }

    QSqlDatabase db = QSqlDatabase::addDatabase(m_qsDatabaseType, qsConnName);
    db.setHostName(m_qsHostName);
    db.setDatabaseName(m_qsDatabase);
    db.setUserName(m_qsUser);
    db.setPassword(m_qsPassWd);
    db.setPort(m_nPort);

    if (!db.open())
    {
        qDebug() << "Open sql error" << db.lastError().text();
        return QSqlDatabase();
    }

    return db;
}

bool CSQLDatabase::IsOpen(QSqlDatabase db)
{
    bool bRes = db.isOpen();//初步判断,这个不准!!!!
    if (bRes) {
        QSqlQuery q(db);
        bRes = q.exec("SELECT 1;");//这个准
        if (!bRes) {//可能超时断开
            qDebug() << "SELECT 1;" << bRes;
            bRes = db.open();//重新连接
            QSqlQuery q(db);
            bRes = q.exec("SELECT 2;");//看看是否连接成功
            qDebug() << "SELECT 2;" << bRes;
        }
    }
    return bRes;
}

void CSQLDatabase::initParas(QString qsHostName, QString qsUser, QString qsPassWd, 
    QString qsDatabase, QString qsDatabaseType, 
    int nPort)
{
    m_qsHostName = qsHostName;
    m_qsUser = qsUser;
    m_qsPassWd=qsPassWd;
    m_qsDatabase=qsDatabase;
    m_qsDatabaseType=qsDatabaseType;
    m_nPort=nPort;

    ExecuteStmt("show TABLES;");
}

bool CSQLDatabase::ExecuteStmt(QString qsSql)
{
    QSqlDatabase db = OpenConnection();
    //if (!db.isOpen())
    if(!IsOpen(db))
        return false;

    QSqlQuery query = db.exec(qsSql);
    //CloseConnection(db);

    if (query.lastError().isValid())
    {
        qDebug() << "Sql error:" << query.lastError();
        return false;
    }

    return true;
}

bool CSQLDatabase::ExecuteStmt(QString qsSql, QList<QVariant> bindList)
{
    QSqlDatabase db = OpenConnection();
    
    if (!IsOpen(db))
        return false;

    bool bRes = false;
    QSqlQuery query = QSqlQuery(qsSql, db);
    int n = 0;
    for (auto v : bindList) {
        query.bindValue(n++, v);
    }
    bRes=query.exec();
    //CloseConnection(db);

    if (query.lastError().isValid())
    {
        qDebug() << "Sql error:" << query.lastError();
        return false;
    }

    return bRes;
}

QSqlQuery CSQLDatabase::ExecuteQuery(QString qsSql)
{
    QSqlDatabase db = OpenConnection();    
    if (!IsOpen(db))
        return QSqlQuery();

    QSqlQuery query = db.exec(qsSql);
    //CloseConnection(db);
    
    if (query.lastError().isValid())
    {
        qDebug() << "Sql error:" << query.lastError();
        return QSqlQuery();
    }

    return query;
}

QSqlQuery CSQLDatabase::ExecuteQuery(QString qsSql, QList<QVariant> bindList)
{
    QSqlDatabase db = OpenConnection();
    if (!IsOpen(db))
        return QSqlQuery();

    QSqlQuery query= QSqlQuery(qsSql,db);
    int n = 0;
    for (auto v : bindList) {
        query.bindValue(n++, v);
    }
    bool bRes=query.exec();

    //CloseConnection(db);

    if (query.lastError().isValid())
    {
        qDebug() << "Sql error:" << query.lastError();
        return QSqlQuery();
    }
    
    return query;
}

 

三、使用

先初始化:

CSQLDatabase::GetInstance()->initParas(sHost, sUserName, sPassword, sDbName, sDbType, nDbPort);

 

posted @ 2023-08-23 21:55  吾非无心  阅读(38)  评论(0编辑  收藏  举报