QT C++数据库ORM 使用QxOrm框架并使用泛型编程 (三)

上一篇 windows下静态使用QxOrm框架并使用泛型编程 (二)

这篇讲如何整合所有的表并且数据库增加字段升级,首先我们需要一张可以记录版本号的表

VersionObject 这个类放置在QxObject里 因为字段不会增加所以我们只需要VersionHandler类即可 不需要映射类

代码如下:VersionObject .h

#ifndef VERSIONOBJECT_H

#define VERSIONOBJECT_H

#include "common.h"

#include <QxOrm.h>

#include <QString>

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<VersionObject> & 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 <QxOrm.h>

#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<VersionObject> Shared_Version;

typedef QList<VersionObject> List_Version;                      //User类数组

typedef qx::QxCollection<int,VersionObject> Collection_Version;  //User容器

class VersionHandler:public IHandler<Shared_Version,Collection_Version,VersionObject>,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<Shared_Version,Collection_Version,VersionObject>::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<Shared_Version,Collection_Version,VersionObject>::insert(t,m_Mutex,m_SqlDatabase);

}

bool VersionHandler::update(Shared_Version &t)

{

    QStringList list;

    return IHandler<Shared_Version,Collection_Version,VersionObject>::update(t,m_Mutex,m_SqlDatabase,list);

}

bool VersionHandler::select(Shared_Version &t)

{

    QStringList list;

    return IHandler<Shared_Version,Collection_Version,VersionObject>::select(t,m_Mutex,m_SqlDatabase,list);

}


为了更好的管理整个数据库的所有表 于是我们需要一个单例类来管理所有的Handler  所以我在SQLModule下新建了一个SQLHelper单例类

代码如下:

SqlHelper.h

#ifndef SQLHELPER_H

#define SQLHELPER_H

#include <QMutex>

#include "SQLModule/QxHandler/UserHandler.h"

#include "SQLModule/QxHandler/VersionHandler.h"

#include <QSqlDatabase>

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<UserHandler> 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<UserHandler>  m_pUser;

    QSharedPointer<VersionHandler> 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<VersionHandler> tem1(new VersionHandler());

    m_pVersion=tem1;

    QSharedPointer<UserHandler>  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"<<dbVersion->version;

        qDebug()<<" qApp->property()"<<qApp->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<QString, qx::IxClass *> * 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 ******"<<pClass->getName() <<pClass->getVersion();

                // 如果表不存在,创建它并设置拥有者

                if (! tables.contains(pClass->getName()))

                {

                    qDebug()<<"***** want to creat table pClass->getName ******:"<<pClass->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  *****:"<<pClass->getName() <<p->getName()<<p->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<UserHandler> SqlHelper::getUser()

{

    return m_pUser;

}


是否有发现SQLHelper 里面有两个方法 isOldVersion() 和updateDatabase() 这个是用于校验当前app版本和数据库版本的方法,直接照抄就可以了修改官方并且验证过了。

还有个common.h

#ifndef COMMON_H

#define COMMON_H

#include <QString>

const QString DATABASE_APP="DataBaseVersion";

const int DATABASE_VERSION=0;          //数据库版本控制

#endif // COMMON_H

main.cpp

#include <QApplication>

#include "common.h"

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    a.setProperty("DataBaseVersion",DATABASE_VERSION);

    return a.exec();

}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,387评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,845评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,091评论 0 246
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,308评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,662评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,795评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,008评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,743评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,466评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,687评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,181评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,531评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,177评论 3 239
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,126评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,902评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,862评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,734评论 2 274