上一篇 windows下静态使用QxOrm框架并使用泛型编程 (二)
这篇讲如何整合所有的表并且数据库增加字段升级,首先我们需要一张可以记录版本号的表
VersionObject 这个类放置在QxObject里 因为字段不会增加所以我们只需要VersionHandler类即可 不需要映射类
代码如下:VersionObject .h
#ifndef VERSIONOBJECT_H
#define VERSIONOBJECT_H
#include "common.h"
#include
#include
class VersionObject
{
public:
VersionObject();
void init();
public:
QString name;
//long name;
long version;
};
QX_REGISTER_PRIMARY_KEY(VersionObject, QString) //主键不是整数类型的时候使用
QX_REGISTER_HPP_IMPORT_DLL(VersionObject, qx::trait::no_base_class_defined, DATABASE_VERSION)
#endif // VERSIONOBJECT_H
VersionObject .cpp
#include "VersionObject.h"
QX_REGISTER_CPP_IMPORT_DLL(VersionObject)
namespace qx
{
template <> void register_class(QxClass
& t) {
t.id(& VersionObject::name, "name");
t.data(& VersionObject::version, "version");
}
}
VersionObject::VersionObject()
{
}
void VersionObject::init()
{
this->name= "qxorm";
this->version=DATABASE_VERSION;
}
VersionHandler.h
#ifndef VERSIONHANDLER_H
#define VERSIONHANDLER_H
#include
#include "IHandler.h"
#include "SQLModule/QxObject/VersionObject.h"
namespace VERSION
{
const QString DATABASE_TYPE="QSQLITE";
const QString CONNECT_NAME="VERSION_CONNECTED";
const QString DATABASENAME="C:/Users/we/Desktop/workTools/demo/version.db";
const QString HOSTNAME="localhost";
const QString USERNAME="root";
const QString PASSWORD="";
}
using namespace VERSION;
class VersionObject;
typedef QSharedPointer
Shared_Version; typedef QList
List_Version; //User类数组 typedef qx::QxCollection
Collection_Version; //User容器 class VersionHandler:public IHandler
,public ISqlInterface {
public:
VersionHandler();
virtual ~VersionHandler();
protected:
virtual void initSqlconnect();
virtual bool createTable();
virtual void disconnect();
public:
bool insert(Shared_Version &t);
bool update(Shared_Version &t);
bool select(Shared_Version &t);
private:
QSqlDatabase m_SqlDatabase;
QMutex m_Mutex;
};
#endif // VERSIONHANDLER_H
VersionHandler.cpp
#include "VersionHandler.h"
VersionHandler::VersionHandler()
{
initSqlconnect();
if(createTable())
{
Shared_Version version(new VersionObject());
version->init();
this->insert(version);
}
}
VersionHandler::~VersionHandler()
{
disconnect();
}
void VersionHandler::initSqlconnect()
{
QMutexLocker locker(&m_Mutex);
if(QSqlDatabase::contains(CONNECT_NAME))
m_SqlDatabase = QSqlDatabase::database(CONNECT_NAME);
else
m_SqlDatabase= QSqlDatabase::addDatabase(DATABASE_TYPE,CONNECT_NAME);
m_SqlDatabase.setDatabaseName(DATABASENAME);
m_SqlDatabase.setHostName(HOSTNAME);
m_SqlDatabase.setUserName(USERNAME);
m_SqlDatabase.setPassword(PASSWORD);
m_SqlDatabase.open();
}
bool VersionHandler::createTable()
{
return IHandler
::createTable(m_SqlDatabase); }
void VersionHandler::disconnect()
{
QMutexLocker locker(&m_Mutex);
if(m_SqlDatabase.isOpen())
m_SqlDatabase.close();
QSqlDatabase::removeDatabase(CONNECT_NAME);
}
bool VersionHandler::insert(Shared_Version &t)
{
return IHandler
::insert(t,m_Mutex,m_SqlDatabase); }
bool VersionHandler::update(Shared_Version &t)
{
QStringList list;
return IHandler
::update(t,m_Mutex,m_SqlDatabase,list); }
bool VersionHandler::select(Shared_Version &t)
{
QStringList list;
return IHandler
::select(t,m_Mutex,m_SqlDatabase,list); }
为了更好的管理整个数据库的所有表 于是我们需要一个单例类来管理所有的Handler 所以我在SQLModule下新建了一个SQLHelper单例类
代码如下:
SqlHelper.h
#ifndef SQLHELPER_H
#define SQLHELPER_H
#include
#include "SQLModule/QxHandler/UserHandler.h"
#include "SQLModule/QxHandler/VersionHandler.h"
#include
namespace SQLHELPER //用于版本升级的
{
const QString DATABASE_TYPE="QSQLITE";
const QString CONNECT_NAME="UPDATE_ALLTABLE";
const QString DATABASENAME="C:/Users/we/Desktop/workTools/demo/qxorm.db";
const QString HOSTNAME="localhost";
const QString USERNAME="root";
const QString PASSWORD="";
}
class SqlHelper
{
public:
static SqlHelper * getInstance();
bool init();
bool isOldVersion(); //查询当前App 的数据库版本是否是以前的 如果是则调用updateDatabase
void updateDatabase();
QSharedPointer
getUser(); private:
SqlHelper(){}
SqlHelper(const SqlHelper&);
SqlHelper& operator=(const SqlHelper);
class CGarbo //单例自动回收
{
public:
CGarbo(){}
~CGarbo()
{
if (SqlHelper::m_pSqlHelper)
{
delete SqlHelper::m_pSqlHelper;
}
}
};
private:
static QMutex m_sMutex;
static SqlHelper *m_pSqlHelper;
static CGarbo m_sCGarbo;
private:
QSharedPointer
m_pUser; QSharedPointer
m_pVersion; };
#endif // SQLHELPER_H
SqlHelper.cpp
#include "SqlHelper.h"
SqlHelper * SqlHelper ::m_pSqlHelper = nullptr;
QMutex SqlHelper::m_sMutex;
SqlHelper::CGarbo SqlHelper::m_sCGarbo;
SqlHelper *SqlHelper::getInstance()
{
SqlHelper* tmp = m_pSqlHelper;
if (tmp == nullptr)
{
QMutexLocker lock(&m_sMutex);
tmp = m_pSqlHelper;
if (tmp == nullptr)
{
tmp = new SqlHelper();
m_pSqlHelper = tmp;
}
}
return m_pSqlHelper;
}
bool SqlHelper::init()
{
QSharedPointer
tem1(new VersionHandler()); m_pVersion=tem1;
QSharedPointer
tem2(new UserHandler()); m_pUser=tem2;
return true;
}
bool SqlHelper::isOldVersion()
{
if(!m_pVersion.isNull())
{
Shared_Version dbVersion(new VersionObject());
dbVersion->init();
m_pVersion->select(dbVersion);
qDebug()<<"dbVersion->version"<
version; qDebug()<<" qApp->property()"<
property("DataBaseVersion").toInt(); qDebug()<<(dbVersion->version < qApp->property("DataBaseVersion").toInt());
return (dbVersion->version < qApp->property("DataBaseVersion").toInt());
}
else
{
return false;
}
}
void SqlHelper::updateDatabase()
{
try
{
int dbversion=qApp->property("DataBaseVersion").toInt();
Shared_Version dbVersion(new VersionObject());
dbVersion->init();
m_pVersion->select(dbVersion);
{
QSqlDatabase db;
if(QSqlDatabase::contains(SQLHELPER::CONNECT_NAME))
db = QSqlDatabase::database(SQLHELPER::CONNECT_NAME);
else
db= QSqlDatabase::addDatabase(SQLHELPER::DATABASE_TYPE,SQLHELPER::CONNECT_NAME);
db.setDatabaseName(SQLHELPER::DATABASENAME);
db.setHostName(SQLHELPER::HOSTNAME);
db.setUserName(SQLHELPER::USERNAME);
db.setPassword(SQLHELPER::PASSWORD);
if(!db.isOpen())
{
db.open();
}
if (dbVersion->version >= dbversion)
{
if(db.isOpen())
{
qDebug("**************** i come here ********************");
db.close();
}
QSqlDatabase::removeDatabase(SQLHELPER::CONNECT_NAME);
return;
}
QSqlQuery query(db);
//获取在QxOrm注册的所有持久化类
qx::QxCollection
* pAllClasses = qx::QxClassX::getAllClasses(); if (! pAllClasses)
{
qAssert(false); return;
}
//将所有表获取到数据库中
QStringList tables = db.tables();
for (long k = 0; k < pAllClasses->count(); k++)
{
qx::IxClass * pClass = pAllClasses->getByIndex(k);
if (! pClass) { continue; }
// 过滤非persitents类
if (pClass->isKindOf("qx::service::IxParameter") || pClass->isKindOf("qx::service::IxService")) { continue; }
// 筛选已经更新的类
if (pClass->getVersion() <= dbVersion->version) { continue; }
qDebug()<<"****** pAllClasses->name ******"<
getName() < getVersion(); // 如果表不存在,创建它并设置拥有者
if (! tables.contains(pClass->getName()))
{
qDebug()<<"***** want to creat table pClass->getName ******:"<
getName(); query.exec("CREATE TABLE " + pClass->getName() + " ( ) WITH (OIDS = FALSE);"
"ALTER TABLE " + pClass->getName() + " OWNER TO \"root\";");
//session += query.lastError();
}
// 如果不存在列,则将其添加到表中
qx::IxDataMemberX * pDataMemberX = pClass->getDataMemberX();
for (long l = 0; (pDataMemberX && (l < pDataMemberX->count_WithDaoStrategy())); l++)
{
qx::IxDataMember * p = pDataMemberX->get_WithDaoStrategy(l);
if (! p || (p->getVersion() <= dbVersion->version)){ continue; }
qDebug()<<"***** add alter pClass->getName *****:"<
getName() < getName()< getSqlType(); query.exec("ALTER TABLE " + pClass->getName() + " ADD COLUMN " + p->getName() + " " + p->getSqlType() + ";");
//session += query.lastError();
if (p->getIsPrimaryKey()) // PRIMARY KEY
{
query.exec("ALTER TABLE " + pClass->getName() + " ADD PRIMARY KEY (" + p->getName() + ");");
//session += query.lastError();
}
if (p->getAllPropertyBagKeys().contains("INDEX")) // INDEX
{
query.exec("CREATE INDEX " + pClass->getName() + "_" + p->getName() + "_idx" +
" ON " + pClass->getName() + " USING " + p->getPropertyBag("INDEX").toString() + " (" + p->getName() + ");");
//session += query.lastError();
}
if (p->getNotNull()) // NOT NULL
{
query.exec("ALTER TABLE " + pClass->getName() + " ALTER COLUMN " + p->getName() + " SET NOT NULL;");
//session += query.lastError();
}
if (p->getAutoIncrement()) // AUTO INCREMENT
{
query.exec("CREATE SEQUENCE " + pClass->getName() + "_" + p->getName() + "_seq" + "; "
"ALTER TABLE " + pClass->getName() + "_" + p->getName() + "_seq" + " OWNER TO \"root\"; "
"ALTER TABLE " + pClass->getName() + " ALTER COLUMN " + p->getName() + " " +
"SET DEFAULT nextval('" + pClass->getName() + "_" + p->getName() + "_seq" + "'::regclass);");
//session += query.lastError();
}
if (p->getDescription() != "") // DESCRIPTION
{
query.exec("COMMENT ON COLUMN " + pClass->getName() + "." + p->getName() + " IS $$" + p->getDescription() + "$$ ;");
//session += query.lastError();
}
}
}
//保存数据库的当前版本
dbVersion->version = dbversion;
m_pVersion->update(dbVersion);
if(db.isOpen())
{
db.close();
}
}
QSqlDatabase::removeDatabase(SQLHELPER::CONNECT_NAME);
}
catch(const qx::dao::sql_error & err)
{
QSqlError sqlError = err.get();
qDebug() << sqlError.databaseText();
qDebug() << sqlError.driverText();
qDebug() << sqlError.number();
qDebug() << sqlError.type();
}
}
QSharedPointer
SqlHelper::getUser() {
return m_pUser;
}
是否有发现SQLHelper 里面有两个方法 isOldVersion() 和updateDatabase() 这个是用于校验当前app版本和数据库版本的方法,直接照抄就可以了修改官方并且验证过了。
还有个common.h
#ifndef COMMON_H
#define COMMON_H
#include
const QString DATABASE_APP="DataBaseVersion";
const int DATABASE_VERSION=0; //数据库版本控制
#endif // COMMON_H
main.cpp
#include
#include "common.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setProperty("DataBaseVersion",DATABASE_VERSION);
return a.exec();
}