基于 主表 + 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执行,支持索引、分页、排序、联表、权限

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


相关推荐
XMYX-013 小时前
28 - Go JSON 数据操作
开发语言·golang·json
Promise微笑1 天前
Geo专家于磊:Json-LD优化实战SOP与双核四驱体系
大数据·人工智能·重构·json
专注VB编程开发20年1 天前
json和python元组,列表,字典对比
开发语言·python·json·php
奇树谦1 天前
深度解析 compile_commands.json:源码到目标码映射的核心枢纽
json
alwaysrun1 天前
C++之轻量级JSON序列库jsoncpp
c++·json·编程语言
彭于晏Yan1 天前
HttpServletRequest 如何读取JSON请求体
spring boot·后端·json
csdn小瓯1 天前
结构化输出实战:Pydantic Schema约束LLM生成JSON
json·状态模式
Dxy12393102162 天前
Python请求方式介绍:JSON、表单及其他常见数据传输格式
数据库·python·json
龙侠九重天2 天前
大型语言模型结构化输出:用 JSON Schema 约束大模型输出
人工智能·语言模型·自然语言处理·大模型·json