一、前言
在中后台系统开发中,数据查询是每个业务模块的核心功能。传统的做法是为每一个实体类编写一套查询逻辑,导致代码重复、维护成本高。
mldong 框架通过 [PageParam.java] 类为核心,结合 MyBatis-Plus 的 QueryWrapper 和自定义注解机制,实现了高度通用化、可扩展的查询模块,大大提升了系统的开发效率和可维护性。
本文将带你深入了解 mldong 框架中通用查询模块的设计思路与实现细节,重点以 sys_user
和 sys_dept
表为例,说明如何构建灵活多变的查询条件,并强调 查询条件生效的前提:SQL 中必须包含对应字段。
二、核心类介绍:PageParam
✅ 类路径:
✅ 核心作用:
- 支持分页参数;
- 支持关键字搜索;
- 支持字段过滤(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)字段举例说明
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")