#include "dbManager.h" #include "logger.h" DatabaseManager::DatabaseManager(QObject* parent) : QObject(parent) { } DatabaseManager::~DatabaseManager() { /*for(auto i = m_connections.constBegin(); i != m_connections.constEnd(); i++) { QSqlDatabase db = i.value(); db.close(); QSqlDatabase::removeDatabase(i.key()); }*/ //见disconnect注释 QList keys = m_connections.keys(); for(int i = 0; i < keys.count(); i++) { QSqlDatabase db = m_connections.take(keys.at(i)); db.close(); } } bool DatabaseManager::addDatabase(const DatabaseConfig& config) { if(m_configs.contains(config.strConnectionName)) { QSqlError error(QString::fromWCharArray(L"配置信息错误"), //QString("Connection name '%1' already exists").arg(config.strConnectionName), QString::fromWCharArray(L"已存在同名的链接: '%1'").arg(config.strConnectionName), QSqlError::ConnectionError); emit errorOccurred(config.strConnectionName, error.databaseText()); return false; } for(auto i = m_configs.constBegin(); i != m_configs.constEnd(); i++) { DatabaseConfig c = i.value(); if(config.strHost == c.strHost && config.nPort == c.nPort && config.strDBType == c.strDBType && config.strDBName == c.strDBName) { QSqlError error(QString::fromWCharArray(L"配置信息错误"), QString::fromWCharArray(L"'%1' 具有相同配置信息").arg(c.strConnectionName), QSqlError::ConnectionError); emit errorOccurred(config.strConnectionName, error.databaseText()); return false; } } m_configs[config.strConnectionName] = config; return true; } void DatabaseManager::removeDatabase(const QString& strConnectionName) { //先断开链接 disconnect(strConnectionName); //从内存中删除 m_configs.remove(strConnectionName); } void DatabaseManager::updataDatabase(const DatabaseConfig& config) { // if(m_configs.contains(config.strConnectionName)) // m_configs[config.strConnectionName] = config; bool isExist = false; QString strConnectionName; for(auto i = m_configs.begin(); i != m_configs.end(); ++i) { if(i.value().strID == config.strID) { isExist = true; strConnectionName = i.key(); break; } } if(isExist) { //通过先删除之前存储的信息再添加新的信息完成信息刷新 if(strConnectionName != config.strConnectionName) { m_configs.remove(strConnectionName); emit updateConnectionName(strConnectionName, config.strConnectionName); } m_configs[config.strConnectionName] = config; } } bool DatabaseManager::connect(const QString& strConnectionName) { LOG_INFO("DB", QString("Connect to %1").arg(strConnectionName)); if(!m_configs.contains(strConnectionName)) { QSqlError error(QString::fromWCharArray(L"配置信息错误"), QString::fromWCharArray(L"没有找到该链接的配置信息"), QSqlError::ConnectionError); emit errorOccurred(strConnectionName, error.databaseText()); LOG_ERROR("DB", QString("Connection failed: %1 due 2%").arg(strConnectionName).arg("no configuration information")); return false; } const DatabaseConfig& config = m_configs[strConnectionName]; QSqlDatabase db = QSqlDatabase::addDatabase(config.strDBType, strConnectionName); db.setHostName(config.strHost); db.setPort(config.nPort); db.setDatabaseName(config.strDBName); db.setUserName(config.strUserName); db.setPassword(config.strPassword); db.setConnectOptions("client_encoding=UTF8"); if(!db.open()) { QString errorText = db.lastError().databaseText(); LOG_ERROR("DB", QString("DB: %1 open failed. connectionName: %2. error: %3") .arg(config.strDBName) .arg(strConnectionName) .arg(errorText/*QString::fromUtf8(errorText.toUtf8())*/)); emit errorOccurred(strConnectionName, QString::fromWCharArray(L"数据库打开失败,详情可见日志文件")); db.close(); db = QSqlDatabase();//重置为无效数据库对象,在下面remove的时候就不会出现"connection '***' is still in use, all queries will cease to work"的警告 QSqlDatabase::removeDatabase(strConnectionName); return false; } m_connections[strConnectionName] = db; emit connectionStatusChanged(strConnectionName, true); return true; } void DatabaseManager::disconnect(const QString& strConnectionName) { if(m_connections.contains(strConnectionName)) { LOG_INFO("DB", QString("Disconnect to %1").arg(strConnectionName)); //按照官方文档,如果数据库移除了对象,db就是一个"悬空的无效数据库链接"(is now a dangling invalid database connection),因为被remove了,但是并没有被delete //加上括号变成局部变量,超出括号后就被自动删除(delete)了,不会再出现"connection '***' is still in use, all queries will cease to work"的警告 { QSqlDatabase db = m_connections.take(strConnectionName); } QSqlDatabase::removeDatabase(strConnectionName); emit connectionStatusChanged(strConnectionName, false); } } QStringList DatabaseManager::conncetions() { return m_connections.keys(); }