QxOrm的使用

简介: 现在在网上看到的QxOrm教程,都是最基础的,只是使用该库的基本创建函数,并没有深入的介绍其强大的功能。所以我想写一个专栏,详细介绍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("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
add_executable(${PROJECT_NAME} WIN32 main.cpp
        ${SOURCE_INCLUDE} ${SOURCE_SRC} ${SOURCE_UI})
#set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set_target_properties(${PROJECT_NAME} PROPERTIES
        CMAKE_MSVC_RUNTIME_LIBRARY_RELEASE "MultiThreaded$<$<CONFIG:Release>:Release>")
target_link_libraries(${PROJECT_NAME} ${REQUIRED_LIBS_QUALIFIED})
target_link_libraries(${PROJECT_NAME} ${LIB_ORM} ${LIB_SPDLOG})

main.cpp

#include <QApplication>
#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 <QDateTime>
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"); 
    }
}

61a8455800b242ccbb099f73c30c3d7e.png

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


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


使用其他类型主键


author.h

#ifndef _QX_BLOG_AUTHOR_H_
#define _QX_BLOG_AUTHOR_H_
#include "precompiled.h"
#include "export.h"
#include <QString>
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 <QString>
#include <tuple>
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文件。

目录
相关文章
QString与char *之间的完美转换,支持含有中文字符的情况
QString与char *之间的完美转换,支持含有中文字符的情况
1512 0
|
10月前
|
SQL 存储 JSON
QxOrm使用Sql语句进行数据库操作
之前介绍了纯使用QxOrm的增删改查,接下来介绍使用QxOrm来执行sql语句。这部分也是有必要的。 QxOrm一共提供了1个类2个方法来执行sql语句
263 0
|
SQL 缓存 Java
殷浩详解DDD系列 第三讲 - Repository模式
# 第三讲 - Repository模式 **写在前面** 这篇文章和上一篇隔了比较久,一方面是工作比较忙,另一方面是在讲Repository之前其实应该先讲Entity(实体)、Aggregate Root(聚合根)、Bounded Context(限界上下文)等概念。但在实际写的过程中,发现单纯讲Entity相关的东西会比较抽象,很难落地。所以本文被推倒重来,从Repository
34849 8
|
10月前
|
数据库 C++
QxOrm的使用-数据操作--增删改查
上一篇我们讲了QxOrm的基本的数据映射操作,这里面再补充一点东西
537 0
|
10月前
|
SQL 缓存 关系型数据库
QxOrm操作数据库
我们在QT应用开发专栏中对数据库操作做了基本的介绍,很多程序员对于数据库的语法并不是很熟悉,我们就需要使用ORM库来弥补该方面的不足
184 0
|
10月前
|
网络安全 Docker 容器
docker启动容器时报错:iptables: No chain/target/match by that name
【已解决】docker启动容器时报错:iptables: No chain/target/match by that name
1872 0
|
10月前
CTK框架 - 通信 - 事件通信和信号槽通信
CTK框架中的事件监听,即观察者模式流程上是这样:接收者注册监听事件->发送者发送事件->接收者接收到事件并响应;相比调用插件接口,监听事件插件间依赖关系更弱,不用指定事件的接收方和发送方是谁。比如我们需要弹出一个界面,可以使用事件来弹出。
156 0
|
10月前
|
SQL 数据可视化 数据库连接
QtSqlite加密--QtCipherSqlitePlugin的使用
上次说了QxOrm的数据库连接、映射和基础的增删改查,但是我们在使用数据库的时候并不希望别人看到我们数据库的内容,我们希望我们的数据库是能被加密的,只有我们用正确的密码才能连接上我们的数据库。加密之后就可以对数据安全作出一定的保障。
226 1
|
10月前
|
容器
QMainWindow
QMainWindow是一个为用户提供主窗口程序 的类,包含一个菜单栏(menu bar)、多个工具栏 (tool bars)、多个锚接部件(dock widgets)、―个 状态栏(status bar )及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器、 图片编辑器等。
93 0
|
10月前
|
存储 数据库
QxOrm数据库事务
数据库事务是作为单个逻辑工作单元执行的一系列操作: ● 如果在执行事务期间未发生错误,则系统将提交事务。 ● 如果在事务期间发生错误,或者用户指定了回滚操作,则事务中的数据操作不会保留到数据库中。
124 1