You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL嵌套JSON数组条件查询及Spring JPA简化实现问询

MySQL嵌套JSON数组条件查询及Spring JPA实现方案

需求说明

从MySQL的JSON字段中检索任务数据,仅展示给assignedTo数组中任意人员或reviewedBy对象对应的人员,匹配条件为mailId。

目标JSON结构

[
    {
        "taskName": null,
        "endDate": null,
        "assignedTo": [
            {
                "mail": "xxxxxxx.com",
                "employeeName": "xyz xyz",
                "departmentName": "ttttt",
                "region": "aaaaa"
            },
            {
                "mail": "zzzz.com",
                "employeeName": "kklkk",
                "departmentName": "tyeeee",
                "region": "iiiii"
            }
        ],
        "assignedBy": null,
        "labels": null,
        "priority": null,
        "special": false,
        "reviewedBy": {
                "mail": "89ui.com",
                "employeeName": "aalkk",
                "departmentName": "opopee",
                "region": "iiiii"
            },
        "description": null
    }
]

有效MySQL查询方案

1. 使用JSON_CONTAINS(推荐,直观易记)

该函数可直接检查JSON数组/对象中是否包含指定的JSON片段,完美匹配需求:

SELECT * FROM taskmaster.tasks
WHERE 
  -- 匹配assignedTo数组中任意人员的mail
  JSON_CONTAINS(assigned_to, '{"mail": "xxxxxxx.com"}')
  -- 匹配reviewedBy对象的mail
  OR JSON_CONTAINS(reviewed_by, '{"mail": "xxxxxxx.com"}');

2. 使用JSON_SEARCH(备选,通过查找路径判断)

通过查找指定mail值在JSON中的路径,若路径存在则说明匹配成功:

SELECT * FROM taskmaster.tasks
WHERE 
  -- 查找assignedTo数组中mail等于指定值的路径
  JSON_SEARCH(assigned_to, 'one', 'xxxxxxx.com', NULL, '$[*].mail') IS NOT NULL
  -- 直接提取reviewedBy的mail进行比较
  OR JSON_EXTRACT(reviewed_by, '$.mail') = 'xxxxxxx.com';

失效原因说明

  • JSON_EXTRACT(assigned_to,"$.mail"):assigned_to是数组,此路径无法正确定位元素,返回NULL。
  • JSON_EXTRACT(assigned_to,"$[*].*"):返回整个数组的所有字段集合(JSON数组),无法直接与字符串"xxxxxxx.com"比较。
  • 指定索引的$[0].mail:仅能匹配数组第一个元素,无法覆盖所有元素。

Spring JPA简化实现

方法1:原生SQL查询(最直接)

在Repository接口中使用@Query注解编写原生SQL,直接复用MySQL的JSON函数:

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;

public interface TaskRepository extends CrudRepository<Task, Long> {

    @Query(value = "SELECT * FROM tasks " +
                   "WHERE JSON_CONTAINS(assigned_to, :mailJson) " +
                   "OR JSON_CONTAINS(reviewed_by, :mailJson)",
           nativeQuery = true)
    List<Task> findTasksByAssignedOrReviewedMail(String mailJson);
}

调用时,需将mail封装为JSON字符串(可借助Jackson工具类避免手动拼接):

// 示例:用Jackson生成JSON参数
ObjectMapper objectMapper = new ObjectMapper();
String mailJson = objectMapper.writeValueAsString(Map.of("mail", "xxxxxxx.com"));
List<Task> tasks = taskRepository.findTasksByAssignedOrReviewedMail(mailJson);

方法2:封装工具类简化参数生成

单独封装一个JSON工具类,统一生成查询所需的JSON参数:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import java.util.Map;

@Component
public class JsonQueryHelper {
    private final ObjectMapper objectMapper;

    public JsonQueryHelper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    public String generateMailQueryParam(String mail) throws JsonProcessingException {
        return objectMapper.writeValueAsString(Map.of("mail", mail));
    }
}

调用时直接注入工具类使用即可,无需手动拼接JSON字符串。


内容的提问来源于stack exchange,提问作者Abrar Md

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:07:51