QxOrm的使用

QxOrm的使用

现在在网上看到的QxOrm教程,都是最基础的,只是使用该库的基本创建函数,并没有深入的介绍其强大的功能。所以我想写一个专栏,详细介绍QxOrm的使用,我会在介绍模块的时候提供对应的例子给大家参考,该篇文章与官方教程相对应,如果您对我写的有不理解的地方,请看官方文档,我这里也不是所有功能都介绍,仅介绍关系型数据库的连接部分,非关系型的请到官网查看。

本篇文章使用的数据库是sqlite,使用的可视化软件是dbeaver。

不做太多的截图,代码在gitee上都有展示,也会贴出具体的代码供学习,博主技术不强,学历不高,如果有问题,请联系我,我会及时修正

  • QxOrm源码地址

  • QxOrm论坛地址

QxOrm 是一个C++库,旨在为C++用户提供对象关系映射 (ORM)功能。
QxOrm由Lionel Marty开发,他自2003年以来一直担任软件开发工程师

基于每个类的简单C++设置函数(如Java中的HibernateXML映射文件),QxOrm库提供以下功能:

  • 持久性:支持最常见的数据库,如SQLite,MySQL,PostgreSQL,Oracle,MS SQL Server,MongoDB(具有1-1,1-n,n-1和n-n关系);
  • 序列化:JSON,二进制和XML格式;
  • 反射(或内省):动态访问类定义,检索属性和调用类方法;
  • HTTP Web服务器:独立的多线程HTTP 1.1 Web服务器(支持SSL / TLS,持久连接,cookie,会话,分块响应,URL调度程序/路由);
  • JSON API:与C++/Qt以外的其他技术(REST Web服务,QML应用程序,脚本语言)的互操作性。

这里不介绍对应的库编译。

接下来使用一个项目来介绍QxOrm的使用。

搭建项目环境

你可以在OxOrm中找到该项目

CMakeLists

cmake_minimum_required(VERSION 3.19)
project(QxOrmDemo)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/output)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/output)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/output)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/output)

set(CMAKE_CXX_STANDARD 17)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

set(QT_VERSION 5)
set(REQUIRED_LIBS Core Gui Widgets PrintSupport Sql )
set(REQUIRED_LIBS_QUALIFIED Qt5::Core Qt5::Gui Qt5::Widgets Qt5::PrintSupport Qt5::Sql)

find_package(Qt${QT_VERSION} COMPONENTS ${REQUIRED_LIBS} REQUIRED)


#自动查找头文件路径函数
macro(FIND_INCLUDE_DIR result curdir)                                        #定义函数,2个参数:存放结果result;指定路径curdir;
    file(GLOB_RECURSE children "${curdir}/*.hpp" "${curdir}/*.h" )           #遍历获取{curdir}中*.hpp和*.h文件列表
    file(GLOB SOURCE_INCLUDE ${children} )                                   #将文件放入 SOURCE_INCLUDE 中
    set(dirlist "")                                                          #定义dirlist中间变量,并初始化
    foreach(child ${children})                                               #for循环
        string(REGEX REPLACE "(.*)/.*" "\\1" LIB_NAME ${child})              #字符串替换,用/前的字符替换/*h
        if(IS_DIRECTORY ${LIB_NAME})                                         #判断是否为路径
            list (FIND dirlist ${LIB_NAME} list_index)                       #判断dirlist是否含有${LIB_NAME}
            if(${list_index} LESS 0)
                LIST(APPEND dirlist ${LIB_NAME})                             #将合法的路径加入dirlist变量中
            else()
            endif()                                                          #结束判断
        endif()
    endforeach()                                                             #结束for循环
    set(${result} ${dirlist})                                                #dirlist结果放入result变量中
endmacro()
#自动查找源文件路径函数
macro(FIND_SRC_DIR result curdir)
    file(GLOB_RECURSE children "${curdir}/*.cpp" "${curdir}/*.cc" "${curdir}/*.cxx")
    file(GLOB SOURCE_SRC ${children} )
    set(dirlist "")
    foreach(child ${children})
        string(REGEX REPLACE "(.*)/.*" "\\1" LIB_NAME ${child})
        if(IS_DIRECTORY ${LIB_NAME})
            list (FIND dirlist ${LIB_NAME} list_index)
            if(${list_index} LESS 0)
                LIST(APPEND dirlist ${LIB_NAME})
            else()
            endif()
        endif()
    endforeach()
    set(${result} ${dirlist})
endmacro()
#调用函数,指定参数
#自动查找头文件路径函数
macro(FIND_UI_DIR result curdir)                                        #定义函数,2个参数:存放结果result;指定路径curdir;
    file(GLOB_RECURSE children "${curdir}/*.ui")           #遍历获取{curdir}中*.hpp和*.h文件列表
    file(GLOB SOURCE_UI ${children} )                                   #将文件放入 SOURCE_INCLUDE 中
    set(dirlist "")                                                          #定义dirlist中间变量,并初始化
    foreach(child ${children})                                               #for循环
        string(REGEX REPLACE "(.*)/.*" "\\1" LIB_NAME ${child})              #字符串替换,用/前的字符替换/*h
        if(IS_DIRECTORY ${LIB_NAME})                                         #判断是否为路径
            list (FIND dirlist ${LIB_NAME} list_index)                       #判断dirlist是否含有${LIB_NAME}
            if(${list_index} LESS 0)
                LIST(APPEND dirlist ${LIB_NAME})                             #将合法的路径加入dirlist变量中
            else()
            endif()                                                          #结束判断
        endif()
    endforeach()                                                             #结束for循环
    set(${result} ${dirlist})                                                #dirlist结果放入result变量中
endmacro()

FIND_SRC_DIR(SRC_DIR_LIST ${PROJECT_SOURCE_DIR}/src)
FIND_INCLUDE_DIR(INCLUDE_DIR_LIST ${PROJECT_SOURCE_DIR}/src)
FIND_UI_DIR(UI_DIR_LIST ${PROJECT_SOURCE_DIR}/src)
#将INCLUDE_DIR_LIST中路径列表加入工程,包括第三方库的头文件路径
include_directories(
        ${INCLUDE_DIR_LIST}                                            #INCLUDE_DIR_LIST路径列表加入工程
        ${PROJECT_SOURCE_DIR}/third_party/QxOrm/include
        ${PROJECT_SOURCE_DIR}/third_party/spdlog/include
)

if (CMAKE_BUILD_TYPE AND (CMAKE_BUILD_TYPE STREQUAL "Debug"))
    file(GLOB LIB_ORM ${PROJECT_SOURCE_DIR}/third_party/QxOrm/libd/*.lib)
    link_directories(${PROJECT_SOURCE_DIR}/thirdParty/QxOrm/libd)
    file(GLOB LIB_SPDLOG ${PROJECT_SOURCE_DIR}/third_party/spdlog/Debug/*.lib)
    link_directories(${PROJECT_SOURCE_DIR}/thirdParty/spdlog/Debug)
else ()
    file(GLOB LIB_ORM ${PROJECT_SOURCE_DIR}/third_party/QxOrm/lib/*.lib)
    link_directories(${PROJECT_SOURCE_DIR}/third_party/QxOrm/lib)
    file(GLOB LIB_SPDLOG ${PROJECT_SOURCE_DIR}/third_party/spdlog/Release/*.lib)
    link_directories(${PROJECT_SOURCE_DIR}/thirdParty/spdlog/Release)
endif ()

add_compile_options("$<$:/utf-8>")
add_compile_options("$<$:/utf-8>")

add_executable(${PROJECT_NAME} WIN32 main.cpp
        ${SOURCE_INCLUDE} ${SOURCE_SRC} ${SOURCE_UI})

#set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>")
set_target_properties(${PROJECT_NAME} PROPERTIES
        CMAKE_MSVC_RUNTIME_LIBRARY_RELEASE "MultiThreaded$<$:Release>")

target_link_libraries(${PROJECT_NAME} ${REQUIRED_LIBS_QUALIFIED})
target_link_libraries(${PROJECT_NAME} ${LIB_ORM} ${LIB_SPDLOG})

main.cpp

#include 
#include "precompiled.h"
#include "person.h"
#include "turbo_log.h"

void databaseInit()
{
    qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
    qx::QxSqlDatabase::getSingleton()->setDatabaseName("./demo.db");
    qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
    qx::QxSqlDatabase::getSingleton()->setUserName("root");
    qx::QxSqlDatabase::getSingleton()->setPassword("");
    QSqlError daoError = qx::dao::create_table<person>();
    if (daoError.type() != QSqlError::NoError)
    {
        TurboLog::instance().getDailyLogger()->error("Table Member:" + daoError.text().toStdString());
    }
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    databaseInit();
    return app.exec();
}

person.h

#ifndef QXORMDEMO_PERSON_H
#define QXORMDEMO_PERSON_H
#include "precompiled.h"
#include "export.h"
#include 

class person
{
public:
    long id;
    QString firstName;
    QString lastName;
    QDateTime birthDate;
};

QX_REGISTER_HPP_APP(person, qx::trait::no_base_class_defined, 0)
#endif //QXORMDEMO_PERSON_H

person.cpp

#include "person.h"
QX_REGISTER_CPP_APP(person)

namespace qx
{
    template <> void register_class(QxClass<person> & t)
    {
        t.setName("t_person"); // 类映射的表名
        t.id(& person::id, "id");// 将id注册为主键  long 的时候会注册成自增主键
        t.data(& person::firstName, "first_name");//person::firstName注册为表first_name列
        t.data(& person::lastName, "last_name"); 
        t.data(& person::birthDate, "birth_date"); 
    }
}

QxOrm的使用_第1张图片

我的项目使用了日志库spdlog作为日志输出,这里不做详细介绍。

上面的例子主键是long默认自增的,如果你需要其他主键的话

使用其他类型主键

author.h

#ifndef _QX_BLOG_AUTHOR_H_
#define _QX_BLOG_AUTHOR_H_
#include "precompiled.h"
#include "export.h"
#include 

class author
{
    QX_REGISTER_FRIEND_CLASS(author)
public:
    QString  m_id;
    QString  m_name;

};

QX_REGISTER_PRIMARY_KEY(author, QString)
QX_REGISTER_HPP_APP(author, qx::trait::no_base_class_defined, 0)

#endif // _QX_BLOG_AUTHOR_H_

author.cpp

#include "author.h"
QX_REGISTER_CPP_APP(author)

namespace qx
{
    template <> void register_class(QxClass<author> & t)
    {
        t.id(&author::m_id, "m_id");
        t.data(& author::m_name, "m_name");
    }
}

这里的QX_REGISTER_PRIMARY_KEY宏就是定义非long主键的时候使用的。

如果你的类成员变量是私有的或者是保护的,则需要使用QX_REGISTER_FRIEND_CLASS来声明一些友元类。不过我这里都是public,QX_REGISTER_FRIEND_CLASS宏也可以不使用。

使用复合主键

author2.h

#ifndef QXORMDEMO_AUTHOR2_H
#define QXORMDEMO_AUTHOR2_H

#include "precompiled.h"
#include "export.h"
#include 
#include 
class author2
{
public:
    typedef std::tuple<QString, long, QString> type_composite_key;
    static QString str_composite_key() { return "author_id_0|author_id_1|author_id_2"; }
    type_composite_key   m_id;
    QString              m_name;
    QDate                m_birthdate;
};
QX_REGISTER_PRIMARY_KEY(author2, author2::type_composite_key)
QX_REGISTER_HPP_APP(author2, qx::trait::no_base_class_defined, 0)

#endif //QXORMDEMO_AUTHOR2_H

author2.cpp

#include "author2.h"

QX_REGISTER_CPP_APP(author2)

namespace qx
{
    template <> void register_class(QxClass<author2> & t)
    {
        t.id(& author2::m_id, author2::str_composite_key());
        t.data(& author2::m_name, "name");
        t.data(& author2::m_birthdate, "birthdate");
    }
}

这样就可以建表成功。具体的可以使用可视化工具查看对应的db文件。

你可能感兴趣的:(QxOrm(更新中),数据库,c++,qt,orm)