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

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


相关推荐
疯狂SQL5 天前
手写高性能在线 JSON 工具|Web Worker 工程化打包 + 语法自动修复 + 多语言代码生成实战
typescript·json·next.js·web worker·前端性能优化·esbuild·源码实战
terry60010 天前
5G视频短信服务商选型全攻略:通道资源、架构能力与成本评估2026最新标准
大数据·人工智能·5g·json·asp.net·信息与通信·数据库架构
前网易架构师-高司机10 天前
带标注的辣椒病叶数据集,识别率95.9%,可识别三种病害和健康叶子,9916张图,支持yolo,coco json,voc xml,文末有模型训练代码
yolo·json·数据集·病害·叶病·病叶·辣椒
PixelBai10 天前
JSON扁平化使用教程:从入门到精通
json
渔舟唱晚,雁阵惊寒11 天前
CSDN博客内容丢失如何恢复?
json
衣乌安、11 天前
JSON-RPC协议
网络协议·rpc·json
PixelBai11 天前
JSON过滤使用教程:从入门到精通
javascript·chrome·json
PixelBai11 天前
JSON过滤实际应用场景案例
json
一生了无挂12 天前
Java处理JSON技巧教学(从基础到高阶实战全覆盖)
java·开发语言·json