头文件
#ifndef DATABASECOMMON_H
#define DATABASECOMMON_H#include <QObject>
#include <QSqlDatabase>
#include <QSqlQueryModel>
#include <QMutex>
class DatabaseCommon: public QObject
{Q_OBJECT
public:void setDatabase(QSqlDatabase db);void setDatabaseName(QString dbName);void setUserName(QString userName);void setPassword(QString password);virtual bool openDatabase() = 0;void closeDatabase();bool execNormalSQL(const QString &sqlString);bool execSelect(const QString &sqlString, QSqlQueryModel &model);bool execTransaction(const QString &sqlString);bool execTransaction(const QStringList &sqlStrings);
private:DatabaseCommon(const DatabaseCommon&) = delete;DatabaseCommon& operator=(const DatabaseCommon&) = delete;
protected:explicit DatabaseCommon(QObject *parent = nullptr){}virtual ~DatabaseCommon();QSqlDatabase mDatabase;QString mDatabaseName = "";QString mUserName = "";QString mPassword = "";QMutex mMutex;
};
class SysRunDatabase : public DatabaseCommon
{Q_OBJECT
public:static SysRunDatabase& Instance(){static SysRunDatabase mInstance;return mInstance;}bool openDatabase() override;
protected:explicit SysRunDatabase(QObject *parent = nullptr){}~SysRunDatabase() override {}
private:SysRunDatabase(const SysRunDatabase&) = delete;SysRunDatabase& operator=(const SysRunDatabase&) = delete;
};#endif
CPP文件
#include "databasecommon.h"
#include <QDebug>
#include <QSqlQuery>
#include <QFile>
#include <QException>
#include <QSqlError>
#include <QMutexLocker>DatabaseCommon::~DatabaseCommon()
{closeDatabase();
}
void DatabaseCommon::setDatabase(QSqlDatabase db)
{QMutexLocker locker(&mMutex);this->mDatabase = db;
}
void DatabaseCommon::setDatabaseName(QString dbName)
{QMutexLocker locker(&mMutex);this->mDatabaseName = dbName;
}
void DatabaseCommon::setUserName(QString userName)
{QMutexLocker locker(&mMutex);this->mUserName = userName;
}
void DatabaseCommon::setPassword(QString password)
{QMutexLocker locker(&mMutex);this->mPassword = password;
}
bool SysRunDatabase::openDatabase()
{QMutexLocker locker(&mMutex);if(!QFile::exists(mDatabaseName)){qCritical() << "not exist " << mDatabaseName;return false;}mDatabase.setDatabaseName(mDatabaseName);mDatabase.setUserName(mUserName);mDatabase.setPassword(mPassword);if(!mDatabase.open()){qCritical() << "open failed."<< mDatabase.lastError().text();return false;}return true;
}
void DatabaseCommon::closeDatabase()
{mDatabase.close();
}
bool DatabaseCommon::execNormalSQL(const QString &sqlString)
{QMutexLocker locker(&mMutex);if(!mDatabase.isOpen()){qCritical() << "Database is closed.";return false;}try{QSqlQuery query(mDatabase);if (!query.exec(sqlString)){throw query.lastError();}return true;}catch (const QSqlError &error){qCritical() << "Error:" << error.text();return false;}
}
bool DatabaseCommon::execSelect(const QString &sqlString, QSqlQueryModel &model)
{QMutexLocker locker(&mMutex);if(!mDatabase.isOpen()){qCritical() << "Database is closed.";return false;}if(!sqlString.startsWith("SELECT", Qt::CaseInsensitive)){qCritical() << "Unsupported operation: " << sqlString;return false;}try{model.setQuery(sqlString, mDatabase);return true;}catch (const QException &ex){qCritical() << "Exception on model.setQuery: " << ex.what();qCritical() << model.lastError().text();return false;}
}
bool DatabaseCommon::execTransaction(const QString &sqlString)
{QMutexLocker locker(&mMutex);if(!mDatabase.isOpen()){qCritical() << "Database is closed.";return false;}if(sqlString.startsWith("SELECT", Qt::CaseInsensitive)){qCritical() << "Unsupported operation: " << sqlString;return false;}if (!mDatabase.transaction()){qCritical() << "Failed to begin transaction:" << mDatabase.lastError().text();return false;}QSqlQuery query(mDatabase);try{if (!query.exec(sqlString)){throw query.lastError();}if (sqlString.trimmed().startsWith("UPDATE", Qt::CaseInsensitive) && query.numRowsAffected() == 0){qWarning() << "Warning: No rows affected by:" << sqlString;}if (!mDatabase.commit()){throw mDatabase.lastError();}return true;}catch (const QSqlError &error){if (!mDatabase.rollback()){qCritical() << "Failed to rollback transaction:" << mDatabase.lastError().text();}qCritical() << "Transaction failed at command:" << query.lastQuery();qCritical() << "Error:" << error.text();return false;}
}
bool DatabaseCommon::execTransaction(const QStringList &sqlStrings)
{QMutexLocker locker(&mMutex);if(!mDatabase.isOpen()){qCritical() << "Database is closed.";return false;}if (!mDatabase.transaction()){qCritical() << "Failed to begin transaction:" << mDatabase.lastError().text();return false;}QSqlQuery query(mDatabase);try{foreach (const QString &sql, sqlStrings){if (!query.exec(sql)){throw query.lastError();}if (sql.trimmed().startsWith("UPDATE", Qt::CaseInsensitive) && query.numRowsAffected() == 0){qWarning() << "Warning: No rows affected by:" << sql;}}if (!mDatabase.commit()){throw mDatabase.lastError();}return true;}catch (const QSqlError &error){if (!mDatabase.rollback()){qCritical() << "Failed to rollback transaction:" << mDatabase.lastError().text();}qCritical() << "Transaction failed at command:" << query.lastQuery();qCritical() << "Error:" << error.text();return false;}
}
使用示例
QSqlDatabase::addDatabase("QSQLITE", "SysRun");
SysRunDatabase::Instance().setDatabase(QSqlDatabase::database("SysRun", false));
SysRunDatabase::Instance().setDatabaseName("123.db");
if(!SysRunDatabase::Instance().openDatabase())
{return false;
}