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

上一篇 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();

}


你可能感兴趣的:(QT C++数据库ORM 使用QxOrm框架并使用泛型编程 (三))