C++/Qt ORM框架QxOrm环境搭建和简单增删改查使用

概要

QxOrm 库是面向 C++/Qt 开发人员的对象关系映射 (ORM)数据库。
QxOrm官网
官网:QxOrm官网链接
QxOrm下载
进入官网Download页面即可下载源码以及说明文档等。
OxOrm
如图所示,目前最新版本为1.4.9。

示例整体结构和环境配置

示例整体结构
如图所示,在案例中app为实际运行窗体项目程序,通过component子项目来统一管理引入QxOrm相关依赖
QxOrm.pro
需要注意的是在component子项目中引入了QxOrm相关依赖后因为项目结构进行拆分,我这里在QxOrm.pro中配置了编译输出库文件指定到app窗体项目程序的lib文件夹下,方便管理debug、release不同模式的QxOrm相关库文件依赖。

在app窗体程序项目中添加相关配置文件:
export.h:

#ifndef EXPORT_H
#define EXPORT_H

#ifdef _BUILDING_QXORM                              // 判断是否正在构建 QxOrm 库
#define QX_DLL_EXPORT  QX_DLL_EXPORT_HELPER         // 如果正在构建,使用 QX_DLL_EXPORT_HELPER 宏作为导出宏
#else
#define QX_DLL_EXPORT  QX_DLL_IMPORT_HELPER         // 如果不是正在构建,使用 QX_DLL_IMPORT_HELPER 宏作为导入宏
#endif

#ifdef _BUILDING_QXORM                              // 判断是否正在构建 QxOrm 库,然后选择使用导出或导入宏
#define QX_REGISTER_HPP  QX_REGISTER_HPP_EXPORT_DLL
#define QX_REGISTER_CPP  QX_REGISTER_CPP_EXPORT_DLL
#else
#define QX_REGISTER_HPP  QX_REGISTER_HPP_IMPORT_DLL
#define QX_REGISTER_CPP  QX_REGISTER_CPP_IMPORT_DLL
#endif

#endif // EXPORT_H

在动态库调用中,使用宏定义有助于处理一些平台和编译器差异,以及提供更灵活和可移植的代码。

precompiled.h:

#ifndef PRECOMPILED_H
#define PRECOMPILED_H

#include <QxOrm.h>
#include "export.h"

#endif // PRECOMPILED_H
// 预编译头文件,此文件写好后几乎不会变动,可以减少后期的编译时间

precompiled.h为预编译头文件,预编译头文件的作用主要是为了提高编译效率。通过预编译头文件,编译器可以事先编译和预处理一些常用的头文件内容,然后将其保存到一个二进制文件中。在后续的编译过程中,可以直接使用这个预编译的头文件,从而避免重复编译相同的头文件内容,提高编译速度。

在这里插入图片描述

最后需要注意的是在窗体程序.pro中配置先前在export.h中编写的动态库调用宏定义能够通过宏定义_BUILDING_QXORM得知项目是否正在编译,这样可以在编译时根据项目是否处于构建状态来选择性地包含或排除某些代码。这在处理库的导出和导入、或者在不同的构建配置下进行条件编译时非常有用。

增删改查

在QxOrm上下文中注册一个类(映射)。
下面是一个示例,展示如何定义一个名为person的类,该类在 QxOrm 上下文中注册了 4 个属性:id、name、age :

person.h:

#ifndef PERSON_H
#define PERSON_H

#include "precompiled.h" // 引入预编译头文件

// 使用 QX_DLL_EXPORT 宏导出 Person 类,用于动态链接库的导出
class QX_DLL_EXPORT Person
{
public:
    long    id;        // ID
    QString name;      // 姓名
    int     age;       // 年龄

    Person() : id(0) { ; }  // 构造函数,初始化 id 为 0
    virtual ~Person() { ; }
};

// 在 QxOrm 中注册 Person 类
QX_REGISTER_HPP(Person, qx::trait::no_base_class_defined, 0)
/* 这个宏对于在 QxOrm 上下文中注册 'person' 类是必要的 */
/* param 1 : 当前要注册的类 => 'person' */
/* param 2 : 基类,如果没有基类,则使用 qx Trait => 'qx::trait::no_base_class_define' */
/* param 3 : 序列化引擎用于提供“上升兼容性”的类版本 */

#endif // PERSON_H

person.cpp:

#include "precompiled.h"   // 预编译头文件,包含了 '#include <QxOrm.h>' 和 '#include "export.h"'
#include "person.h"        // 引入 Person 类的定义
#include <QxOrm_Impl.h>    // 自动内存泄漏检测和 Boost 序列化导出宏

QX_REGISTER_CPP(Person)    // 使用宏注册 Person 类,将其注册到 QxOrm 上下文中

namespace qx
{
    // QxOrm 的类注册模板特化,用于定义 Person 类的属性
    template <> void register_class<QxClass<Person>>(QxClass<Person> & t)
    {
        t.setName("t_person");          // 设置表名为 "t_person"
        t.id(&Person::id, "id");        // 注册 id 属性
        t.data(&Person::name, "name");  // 注册 name 属性
        t.data(&Person::age, "age");    // 注册 age 属性
    }
}

注意:类方法qx::QxClass::id()和qx::QxClass::data()返回类型为qx::IxDataMember的实例(这是注册数据成员的基类) )。通过此实例,可以自定义qx::IxDataMember类的默认行为,例如“注册瞬态数据成员”一章中的示例。

其他注意事项:还可以使用qx::QxClass::fct_0()、qx::QxClass::fct_1()在 QxOrm 上下文中注册函数和类方法(支持静态和非静态方法)等等…此功能是 QxOrm 库内省引擎的一部分。

编写CRUD测试方法:
mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <QxOrm_Impl.h>
#include "precompiled.h"
#include "person.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    void addSqlConnection();	// 添加数据库连接
    void insertData();			// 插入数据
    void deleteData();			// 删除数据
    void updateData();			// 修改数据
    void selectData();			// 查询数据
};
#endif // MAINWINDOW_H

在需要使用到QxOrm的地方引入自动内存泄漏检测和 Boost 序列化导出宏 #include <QxOrm_Impl.h> 和预编译宏 #include “precompiled.h” 以及 数据库映射类,这里是person。

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    addSqlConnection();
    insertData();
    deleteData();
    updateData();
    selectData();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::addSqlConnection()
{
    qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
    qx::QxSqlDatabase::getSingleton()->setDatabaseName("./database.db");
    qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
    qx::QxSqlDatabase::getSingleton()->setUserName("root");
    qx::QxSqlDatabase::getSingleton()->setPassword("");

    QSqlError sqlError;
    QSqlDatabase db = qx::QxSqlDatabase::getDatabase();
    // 检查连接是否有效
    if (db.isValid())
    {
        qDebug() << "数据库连接成功!";
        sqlError = qx::dao::create_table<Person>(); // 尝试创建 Person 表
        if (sqlError.type() == QSqlError::NoError)
        {
            qDebug() << "表创建成功!";
        }
        else
        {
            qDebug() << "表创建失败! 错误信息: " << sqlError.text();
        }
    }
    else
    {
        sqlError = db.lastError();  // 获取最后一次数据库错误信息
        qDebug() << "数据库连接失败!";
        qDebug() << "错误信息: " << sqlError.text();
    }
}

void MainWindow::insertData()
{
    QSqlError daoError;
    // 定义 QSharedPointer 智能指针类型,用于存储 Person 对象
    typedef QSharedPointer<Person> person_ptr;
    // 创建第一个 Person 对象
    person_ptr p1;
    p1.reset(new Person());
    p1->name = "Tom";
    p1->age = 53;

    // 创建第二个 Person 对象
    person_ptr p2;
    p2.reset(new Person());
    p2->name = "Tomy";
    p2->age = 24;

    // 创建第三个 Person 对象
    person_ptr p3;
    p3.reset(new Person());
    p3->name = "Tony";
    p3->age = 23;

    // 定义 QVector 存储 Person 智能指针
    typedef QVector<person_ptr> person_vector;
    person_vector persons;
    persons.push_back(p1);
    persons.push_back(p2);
    persons.push_back(p3);

    // 尝试插入数据
    daoError = qx::dao::insert(persons);
    if (daoError.type() == QSqlError::NoError)
    {
        qDebug() << "数据插入成功!";
    }
    else
    {
        qDebug() << "数据插入失败! 错误信息: " << daoError.text();
    }
}

void MainWindow::deleteData()
{
    QSqlError daoError;
    Person deletePerson;
    deletePerson.id = 3;
    daoError = qx::dao::delete_by_id(deletePerson);
    if (daoError.type() == QSqlError::NoError)
    {
        qDebug() << "数据删除成功!";
    }
    else
    {
        qDebug() << "数据删除成功! 错误信息: " << daoError.text();
    }
}

void MainWindow::updateData()
{
    QSqlError daoError;
    // 获取要更新的记录
    Person updatePerson;
    updatePerson.id = 2; // 假设第二条数据的id为2,具体根据你的数据模型设置

    // 查询数据库,获取第二条数据
    daoError = qx::dao::fetch_by_id(updatePerson);
    if (daoError.type() != QSqlError::NoError)
    {
        qDebug() << "查询记录失败! 错误信息: " << daoError.text();
        return;
    }

    // 修改记录的属性
    updatePerson.name = "Tommy";
    updatePerson.age = 18;
    // 尝试更新数据
    daoError = qx::dao::update(updatePerson);
    if (daoError.type() == QSqlError::NoError)
    {
        qDebug() << "数据更新成功!";
    }
    else
    {
        qDebug() << "数据更新失败! 错误信息: " << daoError.text();
    }
}

void MainWindow::selectData()
{
    QSqlError daoError;
    QList<Person> list_of_person;

    // 尝试从数据库中获取所有的 Person 记录
    daoError = qx::dao::fetch_all(list_of_person);
    if (daoError.type() == QSqlError::NoError)
    {
        qDebug() << "数据查询成功!";
        // 遍历 QList<Person>
        for (const Person& person : list_of_person)
        {
            qDebug() << "ID: " << person.id << ", Name: " << person.name << ", Age: " << person.age;
            // 在这里可以执行其他操作
        }
    }
    else
    {
        qDebug() << "查询所有数据失败! 错误信息: " << daoError.text();
    }

}

具体方体查询QxOrm官方文档:QxOrm manual

测试运行结果

测试运行结果

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值