Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RelationQuery 插件文档

简体中文

简介

RelationQuery 是基于 Drogon ORM 深度封装的链式关联查询增强库,专为 C++ Drogon 后端设计。无需手写复杂联表 SQL,通过链式风格优雅实现一对一、一对多、 多对多、子查询关联,自动完成结果集去重、嵌套对象映射、分页排序、列别名兼容,大幅 简化复杂业务联表开发。插件同时支持同步与协程异步双调用模式,无缝适配 Drogon 异步 编程模型。

核心特性

  • ✅ 支持三种主流关系:hasOne 一对一、hasMany 一对多、manyToMany 多对多
  • ✅ 支持子查询关联查询,可直接嵌套使用
  • ✅ 关联查询采用 LEFT JOIN,保证主表数据不丢失
  • ✅ 自动去重合并一对多 / 多对多结果,避免联表重复数据
  • ✅ 支持自定义表别名、列别名,可解决 MySQL 同名字段冲突
  • ✅ 极简链式调用,语义直观、代码高度简洁
  • ✅ 内置条件筛选、排序、分页、偏移
  • ✅ 自动映射为 std::tuple 嵌套结构,支持 optional / vector 自动组装
  • ✅ 完全兼容原生 Drogon Model,无侵入式接入
  • ✅ 原生支持 C++20 协程,与 Drogon 框架协程体系完全兼容,非阻塞执行数据库查询

使用指南

安装

确保您已经在开发环境中安装并正确配置了 drogon 框架,并安装了 至少一个数据库的开发端(可以通过drogon_ctl --version确认)。

要安装 RelationQuery 插件,可以按照以下步骤执行:

下载代码

cd your_project/plugins
git clone https://github.com/tanglong3bf/RelationQuery.git

compile_flags.txt(可选)

-I./plugins/RelationQuery/src

协程支持说明:使用协程接口需确保项目开启 C++20 及以上编译标准,Drogon 框架 默认已启用协程支持,无需额外配置。若编译器不支持 C++20 标准协程,插件会通过特性 宏自动屏蔽协程接口,仅保留同步接口,编译与运行完全不受影响。

配置

以下是一个在yaml文件配置此插件的示例:

plugins:
  - name: tl::sql::RelationQuery
    config:
      # 使用哪一个数据库客户端完成查询,默认值:default
      db_client_name: default

以下是一个在json文件配置此插件的示例:

{
  "plugins": [
    {
      "name": "tl::sql::RelationQuery",
      "config": {
        // 使用哪一个数据库客户端完成查询,默认值:default
        "db_client_name": "default"
      }
    }
  ]
}

使用示例

下面提供常用场景示例:

  1. 一对一查询(用户 --- 部门)
  2. 一对一 + 一对多(部门 --- 父部门 --- [用户])
  3. 多对多 + 子查询(部门 --- [用户 --- [角色]])
using namespace std;
using namespace drogon;
using namespace drogon::orm;
using namespace tl::sql;
using namespace drogon_model::relation_query_test;  // 测试数据库名

int main()
{
    app().registerBeginningAdvice([] {
        // 获取插件
        const auto *plugin = app().getPlugin<RelationQuery>();
        // 构建一对一查询
        const auto query =
            Query<SysUser>("u")
                .hasOne<SysDept>(JoinOn{"u.dept_id", "d.dept_id"}, "d")
                .orderBy("u.user_id");
        // 查询结果(推荐使用auto,这里只做展示)
        const vector<tuple<SysUser, optional<SysDept>>> result =
            plugin->findAll(query);
    });

    app().registerBeginningAdvice([] {
        const auto *plugin = app().getPlugin<RelationQuery>();
        // 构建一对一以及一对多查询
        const auto query =
            Query<SysDept>("d")
                .hasOne<SysDept>(JoinOn{"d.parent_id", "p.dept_id"}, "p")
                .hasMany<SysUser>(JoinOn{"d.dept_id", "u.dept_id"}, "u")
                .orderBy("d.dept_id")
                .orderBy("u.user_id");
        // 查询结果(推荐使用auto,这里只做展示)
        const vector<tuple<SysDept, optional<SysDept>, vector<SysUser>>>
            result = plugin->findAll(query);
    });

    app().registerBeginningAdvice([] {
        const auto *plugin = app().getPlugin<RelationQuery>();

        // 构建多对多子查询
        auto subQuery =
            Query<SysUser>("u", {"", "", "u_dept_id"})  // 列别名可选
                .manyToMany<SysUserRole, SysRole>(
                    JoinOn{"u.user_id", "ur.user_id"},
                    JoinOn{"ur.role_id", "r.role_id"},
                    "ur",
                    "r",
                    {"ur_user_id",
                     "ur_role_id"},      // 为避免列名冲突,为中间表的列起别名
                    {"", "role_name"});  // 列别名可选
        // 使用子查询
        const auto query =
            Query<SysDept>("d", {"", "dept_name"})  // 列别名可选
                .withSub(subQuery,
                         JoinOn{"d.dept_id", "user_info.u_dept_id"},
                         "user_info")
                .orderBy("d.dept_id")
                .orderBy("user_info.user_id")
                .orderBy("user_info.ur_role_id");
        // 查询结果(推荐使用auto,这里只做展示)
        const vector<
            tuple<SysDept,
                  vector<tuple<SysUser, vector<pair<SysUserRole, SysRole>>>>>>
            result = plugin->findBy(query, "d.name LIKE '%部'");
    });

    app().loadConfigFile("../config.yaml");
    app().run();
    return 0;
}

协程异步查询示例

插件提供与同步接口一一对应的协程版本:findAllCoro、findByCoro。查询构建逻辑 与同步模式完全一致,仅执行入口不同,可在 Drogon 协程 Handler 中通过 co_await 调用,全程不阻塞 IO 线程,适配高并发异步场景。

using namespace std;
using namespace drogon;
using namespace drogon::orm;
using namespace tl::sql;
using namespace drogon_model::relation_query_test;  // 测试数据库名

int main()
{
    app().registerBeginningAdvice([] {
        const auto *plugin = app().getPlugin<RelationQuery>();
        const auto query =
            Query<SysUser>("u")
                .hasOne<SysDept>(JoinOn{"u.dept_id", "d.dept_id"}, "d")
                .orderBy("u.user_id");
        // 仅有这一行发生变动
        // 协程函数中可以直接 co_await 调用
        const auto result = drogon::async_run(plugin->findAllCoro(query));
    });

    app().loadConfigFile("../config.yaml");
    app().run();
    return 0;
}

About

Drogon ORM Enhanced Query Library.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages