QxOrm使用教程

ORM简介

ORM作用:

  1. 统一访问接口。
  2. 简化访问方式。
  3. 实现分层模式。
  4. 提高安全特性。

基本知识

下载QxOrm源代码

gitee下载链接:https://gitee.com/jiangtao008/QxOrm
gitee仓库下载(速度快点)如有问题可去github搜索QxOrm一样可下载。
github下载:https://github.com/QxOrm/QxOrm

QxOrm数据手册

目前未找到pdf,但是在源码中有html网页手册,如下图路径:
在这里插入图片描述
打开index.html文件后,点击如下图即可找到官方手册:
在这里插入图片描述

开源协议

使用QxOrm前一般都需要对源代码进行编译生成动态库,编译过程有时间另起文章。
为什么需要编译动态库,因为QxOrm为GNU/GPLv3开源协议,直接使用源代码则需要公开你的源代码,你的app使用他的源代码编译的动态库也需要公开源代码。。。。。,主要是使用动态库方便很多,所以像这种第三方库,没有特殊需求基本都是编译动态库使用。
其实使用开源软件编译的动态库,LGPL协议明确你的代码不需要开源,而GPL在国内这环境可以不开源!毕竟没人管你
不过开发商业app还是需要注意点,毕竟国内已经有相关案例了。
GPL认知及诉讼案例:https://blog.csdn.net/weixin_42887343/article/details/121157052
GNU/GPL V3快速指南:https://www.gnu.org/licenses/quick-guide-gplv3.html
在这里插入图片描述
图片来源github。

项目准备

(1)首先将QxOrm源代码放在你的项目根目录下,如下图所示:
在这里插入图片描述
(2)我的项目为qt项目,所以使用pro文件管理项目,在项目的pro文件中添加如下代码,具体内容看注释:

#_BUILDING_USER,通过它可以知道项目是否正在编译
DEFINES += _BUILDING_APP

#包含模块的pri文件,一些宏定义使用中需要用到
include($$PWD/QxOrm/QxOrm.pri)

#添加源代码的头文件路劲,后面代码包含头文件的时候就可以使用相对路径了
INCLUDEPATH += $$PWD/QxOrm/include

#添加编译好的动态库,QxOrm源码编译的动态库在QxOrm/lib目录中,最好编译debug、release两个版本
LIBS += -L$$PWD/QxOrm/lib
CONFIG(debug, debug|release) {
    
    
LIBS += -lQxOrmd
} else {
    
    
LIBS +=  -lQxOrm
}

连接数据库

    qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
    qx::QxSqlDatabase::getSingleton()->setDatabaseName("./Users.db");
    qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
    qx::QxSqlDatabase::getSingleton()->setUserName("root");
    qx::QxSqlDatabase::getSingleton()->setPassword("");

创建表格

    qx::dao::create_table<User>();

其中传入的模板-User类是要求的,需要被qx注册,注册对象(数据库中对应的表结构)User示例如下:
tableUser.h文件

#ifndef USER_H
#define USER_H
#include "precompiled.h"

/******************************************************************
 * User 类对应的是数据库中的 User 表,而类的属性对应的是表中的一个字段(列)
 * 所以,User 类实例对应 User 数据库表中的一条记录(record)
 * 以上都需要的Qx注册
 * ***************************************************************/
class APP_DLL_EXPORT User
{
    
    
public:
    User():id(0)
    {
    
     }
    ~User()
    {
    
     }

    //user的属性
    long id;
    QString name;
    int age;
};

/************************************************************
 * QX_REGISTER_HPP_APP 宏是必须的,用于将 User 类注册到 QxOrm 的上下文中
 * 参数一:表示要注册的当前类 - User
 * 参数二:基类,如果没有基类,则使用 qx::trait::no_base_class_defined
 * 参数三:用于序列化的类版本
 * ***********************************************************/
QX_REGISTER_HPP_APP(User, qx::trait::no_base_class_defined, 1)
#endif // USER_H

tableUser.cpp文件

#include "tableUser.h"
#include <QxOrm_Impl.h>

//与QX_REGISTER_HPP_APP宏一样
QX_REGISTER_CPP_APP(User)

namespace qx
{
    
    
    /**************************************************************
     * qx::register_class() 是一个设置函数
     * 用于将 User 类对应的属性 注册到 QxOrm 的上下文中
     * ***********************************************************/
    template <> void register_class(QxClass<User> & t)
    {
    
    
        // 注册 User::id <=> 数据库中的主键
        t.id(&User::id, "id");

        // 注册 User::name 属性,使用的 key 是 name,version 是 1。
        t.data(&User::name, "name", 1);

        // 注册 User::age 属性,使用的 key 是 age。
        t.data(&User::age, "age");
    }
}

其中#include "precompiled.h"为预编译头文件,如下:

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

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

#endif // PRECOMPILED_H

#include "export.h"为动态库调用常用的宏定义,不具体说明了,代码如下:

#ifndef EXPORT_H
#define EXPORT_H

#ifdef _BUILDING_APP
#define APP_DLL_EXPORT  QX_DLL_EXPORT_HELPER
#else
#define APP_DLL_EXPORT  QX_DLL_IMPORT_HELPER
#endif

#ifdef _BUILDING_APP
#define QX_REGISTER_HPP_APP  QX_REGISTER_HPP_EXPORT_DLL
#define QX_REGISTER_CPP_APP  QX_REGISTER_CPP_EXPORT_DLL
#else
#define QX_REGISTER_HPP_APP  QX_REGISTER_HPP_IMPORT_DLL
#define QX_REGISTER_CPP_APP  QX_REGISTER_CPP_IMPORT_DLL
#endif

#endif // EXPORT_H

插入数据

插入数据给出了一系列接口,如下图:
在这里插入图片描述
其中最基本的就是第一个接口了,因为使用的模板,所以插入的数据可以是当个User类实体,也可以是链表、容器、哈希等等。

    QList<User> aList;
    for(int i = 0;i < 500;i ++)
    {
    
    
        User user;
        user.age = qrand() % 90 + 10;
        user.name = QString ("jiangtao %1").arg(i);
        aList.append(user);
        //qx::dao::insert(user);    //插入数据1
    }
    qx::dao::insert(aList);         //插入数据2
    
    QVector<User> aVector;
    qx::dao::insert(aVector);         //插入数据3
    

更新/编辑数据

更新接口如下:
在这里插入图片描述
最常用的接口为update,其更新依据为User中的id值,使用如下:

	//将id为1对应的name改为"test"
    User user_update;
    user_update.id = 1;
    user_update.name = "test";
    qx::dao::update(user_update);

在数据不存在的情况下编辑,使用update将会失败并返回错误信息。如果无法判断数据是否存在,则使用下图接口:
在这里插入图片描述
save接口在此数据库id对应的数据不存在时将会新增,如果存在则是编辑。

删除数据

接口如下,有两种接口,下面的destroy类型的为软删除。
在这里插入图片描述
示例:

    User user_delete;
    user_delete.id = 3;
    qx::dao::delete_by_id(user_delete);                 //1、以id为依据
    QSqlError daoError = qx::dao::delete_all<User>(); 	//2、删除表中所有数据
    qx::QxSqlQuery delete_query("WHERE User.name = 'test 8'");
    qx::dao::delete_by_query<User>(delete_query);     //3、使用过滤语句删除

获取数据

官方手册中说明获取数据有三种方法,1是通过id获取,2是获取所有数据,3是通过过滤条件获取,如下图所示:
在这里插入图片描述
使用id为依据查询的,代码如下:

    User user_fetch;
    user_fetch.id = 225;
    qx::dao::fetch_by_id<User>(user_fetch);
    qDebug() << "Fetch user id:"<<user_fetch.id
             << "   user age: " << user_fetch.age
             << "   use name:"<<user_fetch.name;

判断表中数据是否存在

    User user_fetch;
    user_fetch.id = 225;	//以id为依据
    qx_bool bDaoExist = qx::dao::exist(user_fetch);
    qDebug()<<"exist flag:"<<bDaoExist.toString();

查询方法

个人感觉QxOrm的查询接口比较鸡肋。。。。。。。。。。。,如下图:
在这里插入图片描述
而且他们官方都说了,如果他们的接口无法满足你的需求,就需要使用Qt的QtQuery了。。。。。。,最关键的是,QxOrm查询的结果只能放在链表或容器等数据结构中,而不能转为QSqlQueryModel类型供QtableView直接显示!!!(不知道是不是我没有找到地方,目前无法实现)

接下来提供一些查询示例代码:
(1)sql语句搜索
使用QxSqlQuery 类,说是sql语句吧,又不完全…

    qx::QxSqlQuery query("WHERE User.name = 'test 8'");     
    QList<User> list_of_female;
    qx::dao::fetch_by_query(query, list_of_female);
    for (int i = 0; i < list_of_female.count(); i++)
        ;//your code

(2)单条件搜索

	qx_query query;          
	query.where("author.sex").isEqualTo(author::female);
    qx::dao::fetch_by_query(query, list_of_female);
    for (int i = 0; i < list_of_female.count(); i++)
        ;//your code

(3)组合搜索(官方示例):

    qx_query query;           //搜索3 - 组合搜索
    query.where("sex").isEqualTo(author::female)
         .and_("age").isGreaterThan(38)
         .or_("last_name").isNotEqualTo("Dupont")
         .or_("first_name").like("Alfred")
         .and_OpenParenthesis("id").isLessThanOrEqualTo(999)
         .and_("birth_date").isBetween(date1, date2)
         .closeParenthesis()
         .or_("id").in(50, 999, 11, 23, 78945)
         .and_("is_deleted").isNotNull()
         .orderAsc("last_name", "first_name", "sex")
         .limit(50, 150);
    QList<User> list_of_female;
    qx::dao::fetch_by_query(query, list_of_female);
    for (int i = 0; i < list_of_female.count(); i++)
        ;//your code

查询篇,如果写的qt代码,还是建议使用Qt的QtQuery进行查询,毕竟查询结果可以直接转为QSqlQueryModel、QSqlTableModel等数据模型,然后QtableView、QtableWidget就可以直接调用setModel显示数据。

数据序列化

这个部分就是将程序中的数据转为XML、Json等文件存储,或者反过来的过程,其中程序中的数据可以从数据库中读取,从Json中读取的数据也可以写入数据库中。
序列化代码全部定义在qx::serialization命名空间中,使用如下:
(1)XML文件的读写
目前我是用的QxOrm版本xml的接口暂时未实现,不过代码先贴上,官网也有:

    //=== 将容器中的用户导出到 XML 文件中(序列化) ===
    QVector<User> users;
    qx::serialization::xml::to_file(users, "./export_users.xml");
    //=== 将 XML 中的用户导入至新容器 ===
    QVector<User> usersXmlTmp;
    qx::serialization::xml::from_file(usersXmlTmp, "./export_users.xml");

(2)Json文件的读写

    //=== 将容器中的用户导出到 Json 文件中(序列化) ===
    qx::serialization::json::to_file(users, "./export_users.json");
    //=== 将 Json 文件中的用户导入至新容器 ===
    QVector<User> usersJsonTmp;
    qx::serialization::json::from_file(usersJsonTmp, "./export_users.json");

事务

QxOrm官方原话:

数据库事务是作为单个逻辑工作单元执行的一系列操作。如果事务执行过程中没有发生错误,则系统提交事务;如果在事务过程中发生错误,或者如果用户指定了回滚操作,那么事务中的数据操作不会持久化(保存)到数据库中。

QxOrm 库的qx::QxSession类目的就是自动管理数据库事务,使用非常方便,类中实现操作符重载,直接可以加上各个操作即可,示例代码如下:

    // 创建一个会话:一个有效的线程数据库连接被自动分配给该会话并打开一个事务
    qx::QxSession session;

    session += qx::dao::delete_all<User>();		//删除User表中得所有数据
    session += qx::dao::insert(aList);			//重新加载一些数据(aList自定义的User表格数据)

    updatatableView();	//对数据库做了操作后,更新表格显示

    if(session.isValid())
        QMessageBox::information(nullptr,"提示","事务操作成功!");
    else
        QMessageBox::information(nullptr,"提示","事务操作失败!\n" + session.firstError().text());

其他接口

以下接口中,除了第一个,其他接口很少使用。

(1)计算表中数据量
可知道表中有多少行数据,代码如下:

    long rowCount = qx::dao::count<User>();
    qDebug() << "rowCount: " << rowCount;

(2)克隆用户

UserPtr uClone = qx::clone_to_qt_shared_ptr(*u1);
qDebug() << "Clone from u1: " << uClone->id << uClone->name << uClone->age;

(3)按类名(factory)创建新用户

qx::any uAny = qx::create("User");

(4)将用户插入到 qx::cache

qx::cache::set("users", users);

(5)从 qx::cache 中删除所有元素

qx::cache::clear();

总结

QxOrm还有非常多的功能的,本文只是最最最基本使用,可以说是分享给大家的入门经验。

其中感觉QxOrm除了接口简明外,他的数据库表关联比较强大,官方重点介绍了Relationships篇章(3.8章)。

有时间的话还是可以看看QxOrm的源代码,比如很多接口使用模板,支持类、链表、等各种数据结构,我们可以研究研究实现方式。

文章可能存在很多错误,有了解的望指正,最后希望大家共同学习,共同进步!

おすすめ

転載: blog.csdn.net/weixin_42887343/article/details/120664818