mldong 快速开发框架通用查询模块设计与实现

一、前言

在中后台系统开发中,数据查询是每个业务模块的核心功能。传统的做法是为每一个实体类编写一套查询逻辑,导致代码重复、维护成本高。

mldong 框架通过 [PageParam.java] 类为核心,结合 MyBatis-Plus 的 QueryWrapper 和自定义注解机制,实现了高度通用化、可扩展的查询模块,大大提升了系统的开发效率和可维护性。

本文将带你深入了解 mldong 框架中通用查询模块的设计思路与实现细节,重点以 sys_usersys_dept 表为例,说明如何构建灵活多变的查询条件,并强调 查询条件生效的前提:SQL 中必须包含对应字段


二、核心类介绍:PageParam

✅ 类路径:

[PageParam.java]

✅ 核心作用:

  • 支持分页参数;
  • 支持关键字搜索;
  • 支持字段过滤(EQ, LIKE, IN, BT 等);
  • 支持排序;
  • 构建统一的 QueryWrapper 查询条件;
  • 支持 Swagger 文档展示查询参数说明。

三、PageParam 主要字段解析

字段名 类型 描述
pageNum Integer 当前页码,默认 1
pageSize Integer 每页大小,默认 10,最大 10000
keywords String 关键字搜索内容
searchKeys String 关键字对应的列名(英文逗号分隔)
orderBy String 排序字段,如 id desc, name asc
orderType Integer 排序类型(前端使用)
isCount YesNoEnum 是否查询总条数
includeType Integer 查询模式(或查/与查)
includeIds List 或查 ID 列表
dataScope List 数据范围(组织机构 ID 集合)
filterType / filterTypes Integer / List 过滤类型
excludeWheres String 排除的查询条件(英文逗号分割)

四、构建 QueryWrapper 查询条件

✅ 方法签名:

java 复制代码
public QueryWrapper buildQueryWrapper(Dict dict)

✅ 实现逻辑:

1. 自动识别请求体中的 m_{type}_{column} 格式字段

例如:

json 复制代码
{
  "m_EQ_id": "1",
  "m_LIKE_realName": "张三",
  "m_BT_age": "18,30"
}

会被自动转换为如下 SQL 条件:

sql 复制代码
WHERE id = 1 AND real_name LIKE '%张三%' AND age BETWEEN 18 AND 30

注意字段命名规则m_{操作符}_{字段名},其中字段名应与数据库字段对应(驼峰转下划线),例如:

  • Java字段:realName → 数据库字段:real_name
  • Java字段:mobilePhone → 数据库字段:mobile_phone

2. 支持的查询操作符

操作符 SQL 表达式 示例
EQ = m_EQ_id=1
NE != m_NE_status=1
GT > m_GT_age=18
GE >= m_GE_score=60
LT < m_LT_salary=5000
LE <= m_LE_salary=5000
LIKE LIKE %value% m_LIKE_realName=张三
NLIKE NOT LIKE m_NLIKE_realName=张三
LLIKE LIKE %value m_LLIKE_realName=三
RLIKE LIKE value% m_RLIKE_realName=张
BT BETWEEN m_BT_createTime=2024-01-01,2024-12-31
IN IN m_IN_ids=1,2,3
NIN NOT IN m_NIN_ids=1,2,3

3. 关键字搜索支持多字段匹配

json 复制代码
{
  "keywords": "张三",
  "searchKeys": "realName,nickName"
}

生成 SQL:

sql 复制代码
WHERE real_name LIKE '%张三%' OR nick_name LIKE '%张三%'

4. 排序字段处理

支持多种格式的排序表达式:

latex 复制代码
id desc
id asc
id desc,code asc
id,code asc

最终会被转换为:

sql 复制代码
ORDER BY id DESC, code ASC

5. 排除指定字段查询

json 复制代码
{
  "excludeWheres": "m_EQ_id,m_LIKE_realName"
}

表示这两个字段不参与查询构建。


🔍 五、排除字段查询详解:excludeWheres + excludeWhereList

🧩 问题背景

有时我们希望忽略某些字段的查询条件,比如在接口调试阶段,或者为了防止某些字段被误用。

✅ 参数说明:

字段名 类型 描述
excludeWheres String 要排除的字段名列表,多个用英文逗号分隔
excludeWhereList List 内部临时存储结构,用于判断是否跳过该字段

📌 示例 JSON 请求:

json 复制代码
{
  "pageNum": 1,
  "pageSize": 10,
  "m_EQ_id": 1,
  "m_LIKE_realName": "张三",
  "excludeWheres": "m_EQ_id"
}

✅ 构建逻辑说明:

[buildQueryWrapper()] 方法中:

java 复制代码
if(excludeWhereList.contains(fieldName)) continue;

会跳过 m_EQ_id 字段的构建,只保留 m_LIKE_realName

📝 生成 SQL 条件:

sql 复制代码
WHERE real_name LIKE '%张三%'
-- m_EQ_id 被排除

⚠️ 注意事项:

  • excludeWheres 是外部传入的字段名列表;
  • excludeWhereList 是内部处理时使用的 List<String> 结构;
  • 建议在 Controller 层校验权限后传入敏感字段到 excludeWheres 中,防止越权访问。

六、使用示例:用户管理接口

[UserController.java] 中的 /sys/user/page 接口为例:

java 复制代码
@PostMapping("/sys/user/page")
@ApiOperation(value = "分页查询用户列表")
@SaCheckPermission("sys:user:page")
public CommonResult<CommonPage<UserVO>> page(@RequestBody UserPageParam param) {
    return CommonResult.data(userService.page(param));
}

其中 [UserPageParam] 继承自 [PageParam],支持如下查询:

json 复制代码
{
  "pageNum": 1,
  "pageSize": 10,
  "keywords": "张三",
  "searchKeys": "realName",
  "m_EQ_status": 1,
  "m_BT_age": "18,30",
  "orderBy": "createTime desc",
  "excludeWheres": "m_EQ_id"
}

最终生成 SQL:

sql 复制代码
SELECT * FROM sys_user
WHERE status = 1 AND age BETWEEN 18 AND 30 AND real_name LIKE '%张三%'
ORDER BY create_time DESC
LIMIT 10 OFFSET 0

注意:status 字段不存在于 User.java 中,实际 SQL 应避免使用该字段


七、部门表(Dept)字段举例说明

[Dept.java]

Java字段 数据库字段 示例值
id id 部门ID
parentId parent_id 父级部门ID
name name 部门名称
code code 唯一编码
sort sort 排序字段
enabled enabled 是否启用(1启用 0禁用)
leaderIds leader_ids 部门负责人ID集合
mainLeaderId main_leader_id 分管领导ID
remark remark 备注
createTime create_time 创建时间
createUser create_user 创建人
updateTime update_time 更新时间
updateUser update_user 更新人
isDeleted is_deleted 是否删除(软删除)

✅ 示例查询语句(Dept)

json 复制代码
{
  "pageNum": 1,
  "pageSize": 10,
  "keywords": "研发",
  "searchKeys": "name,code",
  "m_EQ_enabled": 1,
  "m_GT_sort": 5,
  "m_LIKE_pids": "1,2,3",
  "orderBy": "sort asc"
}

生成 SQL:

sql 复制代码
SELECT * FROM sys_dept
WHERE enabled = 1 AND sort > 5 AND pids LIKE '%1,2,3%'
AND (name LIKE '%研发%' OR code LIKE '%研发%')
ORDER BY sort ASC
LIMIT 10 OFFSET 0

八、关键问题:查询条件生效的前提

❌ 问题回顾

当前的 [UserMapper.xml] 中 SQL 为:

xml 复制代码
<select id="selectCustom" resultType="com.mldong.modules.sys.vo.UserVO">
    select t.* from sys_user t ${ew.customSqlSegment}
</select>

这个 SQL 没有连接 sys_dept ,因此使用类似 m_d_LIKE_name="研发部" 的查询会失效。


✅ 正确 SQL 写法(支持多表查询)

xml 复制代码
<select id="selectCustom" resultType="com.mldong.modules.sys.vo.UserVO">
    SELECT u.*
         , d.name AS deptName
         , d.code AS deptCode
         , d.enabled AS deptEnabled
    FROM sys_user u
             LEFT JOIN sys_dept d ON u.dept_id = d.id
    ${ew.customSqlSegment}
</select>

🔍 说明:

  • 使用 LEFT JOIN 关联用户表和部门表;
  • 将部门相关字段别名为 deptName, deptCode, deptEnabled,方便 VO 接收;
  • 若 VO 中没有这些字段,MyBatis 会自动忽略未匹配字段,不会报错。

九、VO 字段建议补充

为了接收上述 SQL 返回的部门信息,建议在 [UserVO] 中添加如下字段:

java 复制代码
@ApiModelProperty("所属部门名称")
private String deptName;

@ApiModelProperty("所属部门编码")
private String deptCode;

@ApiModelProperty("所属部门是否启用")
private Integer deptEnabled;

这样前端就可以直接拿到部门相关信息并展示。


十、查询条件命名调整

❌ 错误写法(无法生效):

json 复制代码
{
  "m_d_LIKE_name": "研发部"
}

✅ 正确写法(需与 VO 字段一致):

json 复制代码
{
  "m_LIKE_deptName": "研发部"
}

生成 SQL:

sql 复制代码
WHERE deptName LIKE '%研发部%'

十一、优势总结

特性 说明
高度通用 一个类支持所有实体的查询逻辑
灵活过滤 支持 EQ、LIKE、IN、BT 等多种操作符
关键字搜索 多字段模糊匹配
排序支持 支持字段排序及多个排序字段
排除查询 可忽略某些字段
支持表别名 m_u_EQ_id, m_d_LIKE_name
权限控制 结合 dataScope 支持数据权限

十二、典型应用场景

功能 请求参数 SQL 条件 说明
查询姓名为张三的用户 "m_EQ_realName":"张三" WHERE real_name = '张三' 生效
查询手机号在某个区间 "m_BT_mobilePhone":"13800000000,13900000000" WHERE mobile_phone BETWEEN ... 生效
查询属于"研发部"的用户 "m_EQ_deptName":"研发部" WHERE deptName = '研发部' 生效
查询部门已启用的用户 "m_EQ_deptEnabled":1 WHERE deptEnabled = 1 生效
排除某些字段查询 "excludeWheres":"m_EQ_id" 跳过 m_EQ_id 字段 生效

十三、设计亮点

✅ 1. 基于命名规范的自动映射

字段命名规则:m_{type}_{column},例如:

  • m_EQ_id
  • m_LIKE_realName
  • m_BT_createTime

系统会自动识别并构建相应的查询条件。

✅ 2. 支持嵌套字段查询

例如:

json 复制代码
{
  "m_u_EQ_id": 1,
  "m_d_LIKE_name": "研发部"
}

可构建类似:

sql 复制代码
u.id = 1 AND d.name LIKE '%研发部%'

✅ 3. 查询条件可扩展性强

只需在继承类中添加新的 m_XXX 字段即可扩展查询条件。

✅ 4. 支持前后端联动的查询构建

  • 后端构建 QueryWrapper;
  • 前端根据 buildQuerySchema() 渲染查询表单项;
  • 查询参数由前端传入后端自动识别。

十四、结语

PageParam\] 是 mldong 框架中非常实用且设计巧妙的通用查询类,它不仅简化了后端开发流程,还极大地提升了系统的灵活性与可维护性。 欢迎关注【mldong】开源项目,后续将持续分享字典扩展、低代码平台构建等内容。 如果你也想打造一个灵活可扩展的字典系统,欢迎 Star 我们的开源项目 [mldong](https://link.juejin.cn?target=https%3A%2F%2Fgitee.com%2Fmldong%2Fmldong "https://gitee.com/mldong/mldong")。 更多关于字典、低代码平台构建的内容,欢迎关注【mldong】公众号,第一时间获取更新通知! 📌 如需获取完整源码,请访问 Gitee 地址: 🔗 [gitee.com/mldong/mldo...](https://link.juejin.cn?target=https%3A%2F%2Fgitee.com%2Fmldong%2Fmldong "https://gitee.com/mldong/mldong")

相关推荐
GiraKoo6 分钟前
【GiraKoo】C++11的新特性
c++·后端
MO2T11 分钟前
使用 Flask 构建基于 Dify 的企业资金投向与客户分类评估系统
后端·python·语言模型·flask
云动雨颤18 分钟前
Java并发性能优化|读写锁与互斥锁解析
java
光溯星河19 分钟前
【实践手记】Git重写已提交代码历史信息
后端·github
ldj202031 分钟前
Centos 安装Jenkins
java·linux
PetterHillWater38 分钟前
Trae中实现OOP原则工程重构
后端·aigc
hqxstudying39 分钟前
Intellij IDEA中Maven的使用
java·maven·intellij-idea
圆滚滚肉肉41 分钟前
后端MVC(控制器与动作方法的关系)
后端·c#·asp.net·mvc
SimonKing41 分钟前
拯救大文件上传:一文彻底彻底搞懂秒传、断点续传以及分片上传
java·后端·架构
深栈解码42 分钟前
JUC并发编程 内存布局和对象头
java·后端