基于 主表 + JSON 自定义字段的条件查询

基于 主表 + JSON 自定义字段条件查询完整设计(若依 SpringBoot 最佳实践)

你现在的核心问题:
自定义字段存在 JSON 里,如何像普通字段一样支持:等于、大于、小于、区间、模糊、下拉筛选?

生产可用、高性能、兼容若依分页、支持多厂家、无侵入 的完整方案。


一、核心方案:MySQL JSON 函数查询(官方标准)

MySQL 5.7+/8.0+ 原生支持 JSON 字段条件查询,性能极高,支持索引,不用改表。

通用 JSON 查询语法(直接用)

假设 JSON 字段:custom_field_json

json 复制代码
{"supplier":"A厂","checkResult":"合格","inspectTime":"2025-12-25","qty":100}

1. 等值查询

sql 复制代码
AND custom_field_json->>'$.supplier' = 'A厂'

2. 数字大于/小于/区间

sql 复制代码
AND custom_field_json->>'$.qty' > 100
AND custom_field_json->>'$.qty' BETWEEN 50 AND 200

3. 日期区间

sql 复制代码
AND custom_field_json->>'$.inspectTime' >= '2025-01-01'
AND custom_field_json->>'$.inspectTime' <= '2025-12-31'

4. 模糊查询

sql 复制代码
AND custom_field_json->>'$.supplier' LIKE '%A厂%'

5. 不为空

sql 复制代码
AND custom_field_json->>'$.supplier' IS NOT NULL

二、后端架构设计(若依风格)

目标

前端传入:

js 复制代码
customParams: {
  supplier: "A厂",
  qtyMin: 50,
  qtyMax: 200,
  inspectTimeStart: "2025-01-01",
  inspectTimeEnd: "2025-12-31"
}

后端自动拼接 JSON 查询条件 ,兼容若依 startPage() 分页。


三、完整实现代码(直接复制可用)

1. 给 DTO / 实体增加查询字段

MesProductionOrder.java 增加查询专用字段

java 复制代码
// 自定义字段查询条件(非数据库字段)
@TableField(exist = false)
private Map<String, Object> customParams;

2. 构造 XML 动态 SQL(核心!)

MesProductionOrderMapper.xml

xml 复制代码
<select id="selectCustomOrderList" resultType="com.ruoyi.mes.domain.MesProductionOrder">
    SELECT * FROM mes_production_order
    WHERE del_flag = '0'
    <if test="orderNo != null and orderNo != ''">
        AND order_no = #{orderNo}
    </if>

    <!-- ====================== JSON 自定义字段查询 ====================== -->
    <if test="customParams != null">
        <!-- 文本类型 = -->
        <if test="customParams.supplier != null and customParams.supplier != ''">
            AND custom_field_json->>'$.supplier' = #{customParams.supplier}
        </if>

        <!-- 数字区间 -->
        <if test="customParams.qtyMin != null">
            AND custom_field_json->>'$.qty' >= #{customParams.qtyMin}
        </if>
        <if test="customParams.qtyMax != null">
            AND custom_field_json->>'$.qty' <= #{customParams.qtyMax}
        </if>

        <!-- 日期区间 -->
        <if test="customParams.inspectTimeStart != null">
            AND custom_field_json->>'$.inspectTime' >= #{customParams.inspectTimeStart}
        </if>
        <if test="customParams.inspectTimeEnd != null">
            AND custom_field_json->>'$.inspectTime' <= #{customParams.inspectTimeEnd}
        </if>

        <!-- 模糊查询 -->
        <if test="customParams.likeSupplier != null and customParams.likeSupplier != ''">
            AND custom_field_json->>'$.supplier' LIKE concat('%', #{customParams.likeSupplier}, '%')
        </if>
    </if>
</select>

3. Mapper

java 复制代码
List<MesProductionOrder> selectCustomOrderList(MesProductionOrder order);

4. Service

java 复制代码
public List<MesProductionOrder> selectList(MesProductionOrder order) {
    return baseMapper.selectCustomOrderList(order);
}

5. Controller(若依标准写法)

java 复制代码
@GetMapping("/list")
public TableDataInfo list(MesProductionOrder order) {
    startPage();
    List<MesProductionOrder> list = service.selectList(order);
    return getDataTable(list);
}

四、动态字段查询(真正的自定义字段任意筛选)

上面是固定字段,但你要的是:用户配置什么字段,就能按什么字段查

终极方案:动态拼接 JSON SQL(生产级)

后端工具类:生成自定义查询条件

java 复制代码
public class CustomFieldSqlBuilder {

    /**
     * 动态构建自定义字段查询SQL
     */
    public static String buildJsonSql(Map<String, Object> params) {
        if (params == null || params.isEmpty()) return "";

        StringBuilder sql = new StringBuilder();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            Object val = entry.getValue();
            if (val == null || StringUtils.isEmpty(val.toString())) continue;

            // 规则:
            // xxx -> 等值
            // xxx_min -> 大于等于
            // xxx_max -> 小于等于
            // xxx_like -> 模糊

            if (key.endsWith("_min")) {
                String field = key.replace("_min", "");
                sql.append(" AND custom_field_json->>'$.").append(field).append("' >= #{customParams.").append(key).append("}");
            } else if (key.endsWith("_max")) {
                String field = key.replace("_max", "");
                sql.append(" AND custom_field_json->>'$.").append(field).append("' <= #{customParams.").append(key).append("}");
            } else if (key.endsWith("_like")) {
                String field = key.replace("_like", "");
                sql.append(" AND custom_field_json->>'$.").append(field).append("' LIKE concat('%', #{customParams.").append(key).append("}, '%')");
            } else {
                sql.append(" AND custom_field_json->>'$.").append(key).append("' = #{customParams.").append(key).append("}");
            }
        }
        return sql.toString();
    }
}

XML 使用动态 SQL

xml 复制代码
<select id="selectList" resultType="MesProductionOrder">
    SELECT * FROM mes_production_order
    WHERE del_flag = '0'
    ${customSql}
</select>

Service 传入

java 复制代码
String sql = CustomFieldSqlBuilder.buildJsonSql(order.getCustomParams());
order.setCustomSql(sql);
return mapper.selectList(order);

✅ 效果:前端传任意自定义字段,后端自动生成查询条件


五、性能优化(千万级不卡顿)

给 JSON 字段建索引

sql 复制代码
-- 等值查询索引
CREATE INDEX idx_json_supplier ON mes_production_order ((custom_field_json->>'$.supplier'));

-- 数字/日期索引
CREATE INDEX idx_json_qty ON mes_production_order ((custom_field_json->>'$.qty'));
CREATE INDEX idx_json_time ON mes_production_order ((custom_field_json->>'$.inspectTime'));

加索引后,JSON 查询速度 = 普通字段速度


六、前端对接格式

js 复制代码
queryParams: {
  orderNo: "MO2025001",
  // 自定义字段查询
  customParams: {
    supplier: "A厂",
    qtyMin: 50,
    qtyMax: 200,
    inspectTimeStart: "2025-01-01",
    inspectTimeEnd: "2025-12-31",
    supplierLike: "A厂"
  }
}

七、总结(最精简核心)

自定义字段条件查询 = 3 步

  1. 前端 传入 customParams 动态条件
  2. 后端 自动拼接 JSON->>'$.字段' 查询语句
  3. MySQL执行,支持索引、分页、排序、联表、权限

无大表、无联表、高性能、可动态扩展、适配多厂家


相关推荐
落羽的落羽3 小时前
【项目】JsonRpc框架——开发实现2(业务层)
linux·数据结构·c++·人工智能·算法·json·动态规划
ward RINL19 小时前
WorkBuddy 自定义模型配置踩坑记录:models.json、/v1、API Key 一次讲清楚
json
m0_7381207219 小时前
渗透测试基础——一文详解JSONP跨域劫持漏洞原理与利用
服务器·安全·web安全·json
Super Scraper1 天前
如何使用 cURL 发送 JSON:-d、--json 及常见错误的完整指南
人工智能·爬虫·python·自动化·json·mcp
●VON1 天前
AtomGit Flutter鸿蒙客户端:安全JSON解析
安全·flutter·华为·json·harmonyos·鸿蒙
加号32 天前
【C#】 JSON 序列化与反序列化:从入门到最佳实践
c#·json
li星野2 天前
FastAPI 响应类型完全指南:从 JSON 到流式响应、异常处理与输出模型
前端·json·fastapi
就叫飞六吧2 天前
JSON 与 JSON Schema:从“数据快递”到“使用说明书”
json
奇树谦2 天前
YAML、XML、JSON、TOML、INI、CSV 全面对比:配置文件和数据交换到底该怎么选?
xml·json
TheRouter3 天前
LLM 流式输出工程实践:SSE、背压、断流重连与JSON 流解析的 6 个生产陷阱
人工智能·json