Qt下簡單工廠模式實現多種數據庫操作
簡單工廠
基於簡單的工廠設計模式,由單一工廠生產數據庫連接基類的派生類對象。
數據庫連接基類
配合Qt自帶的數據庫類。
#ifndef SQLCOMMON_H
#define SQLCOMMON_H
#include <QtSql>
class QSqlCommon
{
public:
virtual bool connectDataBase(QString dbName, QString connectName, QString ip, QString user, QString pwd, int port, QString& errorinfo) = 0;
virtual void disconnectDataBase();
virtual QSqlDatabase& getDBHandle();
private:
QSqlDatabase m_db; // 數據庫連接句柄
};
#endif // SQLCOMMON_H
cpp:
#include "sqlcommon.h"
void QSqlCommon::disconnectDataBase()
{
if(m_db.open())
{
m_db.close();
}
}
QSqlDatabase &QSqlCommon::getDBHandle()
{
return m_db;
}
數據庫連接派生類
#ifndef QSQLCONNECTPRODUCT_H
#define QSQLCONNECTPRODUCT_H
#include "sqlcommon.h"
class MySQLConnect: public QSqlCommon
{
public:
bool connectDataBase(QString dbName, QString connectName, QString ip, QString user, QString pwd, int port, QString& errorinfo);
};
class SQLServerConnect: public QSqlCommon
{
public:
bool connectDataBase(QString dbName, QString connectName, QString ip, QString user, QString pwd, int port, QString& errorinfo);
};
#endif // QSQLCONNECTPRODUCT_H
cpp:
#include "QSqlConnectProduct.h"
bool MySQLConnect::connectDataBase(QString dbName, QString connectName, QString ip, QString user, QString pwd, int port, QString& errorinfo)
{
if(getDBHandle().isOpen())
{
getDBHandle().close();
}
getDBHandle() = QSqlDatabase::addDatabase("QMYSQL", connectName);
getDBHandle().setDatabaseName(dbName);
getDBHandle().setHostName(ip);
getDBHandle().setUserName(user);
getDBHandle().setPassword(pwd);
getDBHandle().setPort(port);
if(getDBHandle().open())
{
return true;
}
else
{
errorinfo = getDBHandle().lastError().text();
return false;
}
}
bool SQLServerConnect::connectDataBase(QString dbName, QString connectName, QString ip, QString user, QString pwd, int port, QString& errorinfo)
{
if(getDBHandle().isOpen())
{
getDBHandle().close();
}
getDBHandle() = QSqlDatabase::addDatabase("QODBC", connectName);
getDBHandle().setDatabaseName(QString("DRIVER={SQL SERVER};SERVER=%1;DATABASE=%2").arg(ip).arg(dbName));
getDBHandle().setUserName(user);
getDBHandle().setPassword(pwd);
getDBHandle().setPort(port);
if(getDBHandle().open())
{
return true;
}
else
{
errorinfo = getDBHandle().lastError().text();
return false;
}
}
數據庫連接工廠類
#ifndef QSQLFACTORY_H
#define QSQLFACTORY_H
#include "QSqlConnectProduct.h"
class QSqlFactory
{
QSqlFactory();
public:
enum SQLTYPE
{
MYSQL = 0,
SQLSERVER
};
static QSqlCommon*CreateConnect(SQLTYPE sqlType);
};
#endif // QSQLFACTORY_H
cpp:
#include "QSqlFactory.h"
QSqlFactory::QSqlFactory()
{
}
QSqlCommon *QSqlFactory::CreateConnect(QSqlFactory::SQLTYPE sqlType)
{
QSqlCommon *pSqlConnect = NULL;
switch(sqlType)
{
case MYSQL:
{
pSqlConnect = new MySQLConnect();
break;
}
case SQLSERVER:
{
pSqlConnect = new SQLServerConnect();
break;
}
default:
{
break;
}
}
return pSqlConnect;
}
調用的時候只需要創建產品的基類指針,創建不同的類型連接,就可以操作多中數據庫。
QSqlCommon *m_dbCommon; // 成員對象
m_dbCommon = QSqlFactory::CreateConnect(QSqlFactory::SQLSERVER);
m_dbCommon = QSqlFactory::CreateConnect(QSqlFactory::MYSQL);
// 若要同時操作需要多個指針
結合Qt的Model-View可以對數據庫進行快捷操作。
結合Qt類庫操作數據庫
比如我的UI界面創建了一個treewidget和tableview兩個控件,舉個例子,連接數據庫後顯示庫名,表名等,雙擊表名顯示數據的功能(Navicat:我有理由懷疑你再搞事情…)。
在比如按鈕的槽函數(消息函數)中,
m_dbCommon = QSqlFactory::CreateConnect(QSqlFactory::MYSQL);
connect(ui->treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(onItemDoubleClicked(QTreeWidgetItem*,int)));
QString errorInfo;
if(m_dbCommon->connectDataBase("expressway", "mysqlConnection", "localhost", "root", "soloman", 3306, errorInfo))
{
qDebug() << "open mysql success";
ui->treeWidget->clear();
m_treeItemRoot = new QTreeWidgetItem(QStringList(m_dbCommon->getDBHandle().hostName()));
QList<QTreeWidgetItem*> _itemList;
QSqlQuery _query(m_dbCommon->getDBHandle());
_query.exec("show databases;");
while(_query.next())
{
QString _strName = _query.value(0).toString();
QTreeWidgetItem *_tItem = new QTreeWidgetItem(m_treeItemRoot, QStringList(_strName));
_itemList << _tItem;
}
m_treeItemRoot->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
foreach (QTreeWidgetItem* item, _itemList)
{
_query.exec(QString("show tables in %1;").arg(item->text(0)));
while(_query.next())
{
QString _strName = _query.value(0).toString();
QTreeWidgetItem *_childItem = new QTreeWidgetItem(item, QStringList(_strName));
_childItem->setData(0, 0, _strName);
_childItem->setData(0, 1, "mysqltable");
}
}
ui->treeWidget->addTopLevelItem(m_treeItemRoot);
}
else
{
qDebug() << "failed open" << errorInfo;
}
connect可以放在別的地方,這裏只是告訴讀者有這個操作。
在treewidget的item雙擊事件裏,
void QSqlConnect::onItemDoubleClicked(QTreeWidgetItem *item, int column)
{
if(item->data(0, 1).toString() == "mysqltable")
{
QString _str = QString("select * from %1 limit 0 ,1000").arg(item->text(column).trimmed());
QSqlQuery _query(_str, m_dbCommon->getDBHandle());
QSqlQueryModel *_queryModel = new QSqlQueryModel();
_queryModel->setQuery(_query);
ui->tableView->setModel(_queryModel);
}
else
{
QString _str = QString("select top 1000 * from dbo.%1").arg(item->text(column).trimmed());
QSqlQuery _query(_str, m_dbCommon->getDBHandle());
QSqlQueryModel *_queryModel = new QSqlQueryModel();
_queryModel->setQuery(_query);
ui->tableView->setModel(_queryModel);
}
}
關於ModelView更多的操作與技巧,有興趣的讀者可以自行查閱相關資料。