頭文件
# 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 ;
}