MyBatis Plus 如何使用 JSON_CONTAINS 精准匹配数据库中的 JSON 数组?

MyBatis Plus 如何使用 JSON_CONTAINS 精准匹配数据库中的 JSON 数组?
最新回答
搖到月亮灣

2023-10-18 09:59:03

在 MyBatis Plus 中,使用 JSON_CONTAINS 实现 MySQL JSON 数组的精准匹配需结合数据库原生 JSON 函数,针对纯数组和对象数组分别处理。以下是具体实现方法及注意事项:

一、纯数组的精准匹配

当数据库字段 goods_tips_id_list 存储的是纯数字数组(如 [1617784249885577217, 1615226392250040321]),且需匹配单个元素时:

String tipId = "1617784249885577217";wrapper.and(new Consumer<QueryWrapper<Object>>() { @Override public void accept(QueryWrapper<Object> queryWrapper) { queryWrapper.last("JSON_CONTAINS(goods_tips_id_list, '" + tipId + "')"); }});

关键点

  • 直接传入字符串形式的数字,MySQL 会自动转换为 JSON 数值类型匹配。
  • 若字段存储的是字符串数组(如 ["1617784249885577217"]),则需保持类型一致:String tipIdStr = ""1617784249885577217""; // 添加双引号queryWrapper.last("JSON_CONTAINS(goods_tips_id_list, " + tipIdStr + ")");
二、对象数组的精准匹配

当字段存储对象数组(如 [{"id":1615226392250040321}, {"id":1617784249885577217}]),需构造完整的 JSON 对象字符串进行匹配:

List<Long> tipIds = Arrays.asList(1615226392250040321L, 1617784249885577217L);// 构造JSON对象数组字符串(示例为匹配任意一个对象)String jsonCondition = "[{"id":" + tipIds.get(0) + "}]"; // 若需同时匹配多个对象,需构造完整数组:// String jsonCondition = "[{"id":1615226392250040321}, {"id":1617784249885577217}]";wrapper.and(new Consumer<QueryWrapper<Object>>() { @Override public void accept(QueryWrapper<Object> queryWrapper) { queryWrapper.last("JSON_CONTAINS(goods_tips_id_list, '" + jsonCondition + "')"); }});

进阶用法

  1. 精确匹配整个数组(顺序和内容完全一致):

    String exactMatchJson = "[{"id":1615226392250040321}, {"id":1617784249885577217}]";queryWrapper.last("JSON_CONTAINS(goods_tips_id_list, '" + exactMatchJson + "')");
  2. 使用路径表达式(MySQL 8.0+):

    // 匹配数组中任意对象的id字段queryWrapper.last("JSON_EXISTS(goods_tips_id_list, '$.[*].id') AND " + "JSON_SEARCH(goods_tips_id_list, 'one', " + tipIds.get(0) + ", NULL, '$.id') IS NOT NULL");
三、安全优化建议
  1. 防止SQL注入:使用 PreparedStatement 参数化查询(MyBatis Plus 3.5.0+ 支持):

    wrapper.apply("JSON_CONTAINS(goods_tips_id_list, {0})", JSON.toJSONString(tipIds));
  2. 类型校验:确保Java对象与JSON字段类型一致,例如:

    // 数字数组转JSON时避免科学计数法JSON.toJSONString(tipIds, SerializerFeature.DisableCircularReferenceDetect);
  3. 性能优化:对JSON字段添加索引(MySQL 5.7+支持生成列索引):

    ALTER TABLE your_table ADD COLUMN tips_id_search VARCHAR(255) GENERATED ALWAYS AS (goods_tips_id_list->>'$[*].id') STORED,ADD INDEX idx_tips_id (tips_id_search);
四、常见问题处理
  1. 错误处理:若出现 Invalid JSON text 错误,检查:

    JSON字符串是否包含未转义的特殊字符

    数组括号是否匹配

    对象键是否加双引号

  2. 版本兼容性

    MySQL 5.7.8+ 支持 JSON_CONTAINS

    MySQL 8.0+ 推荐使用 JSON_TABLE 进行复杂查询

  3. 调试技巧

    // 先打印生成的SQL验证JSON格式System.out.println(wrapper.getCustomSqlSegment());// 手动执行SQL确认结果

通过以上方法,可实现MyBatis Plus对MySQL JSON数组的高精度匹配,兼顾安全性与性能。实际开发中建议结合业务场景选择简单匹配或复杂路径查询。