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 + "')"); }});关键点:
当字段存储对象数组(如 [{"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 + "')"); }});进阶用法:
精确匹配整个数组(顺序和内容完全一致):
String exactMatchJson = "[{"id":1615226392250040321}, {"id":1617784249885577217}]";queryWrapper.last("JSON_CONTAINS(goods_tips_id_list, '" + exactMatchJson + "')");使用路径表达式(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");防止SQL注入:使用 PreparedStatement 参数化查询(MyBatis Plus 3.5.0+ 支持):
wrapper.apply("JSON_CONTAINS(goods_tips_id_list, {0})", JSON.toJSONString(tipIds));类型校验:确保Java对象与JSON字段类型一致,例如:
// 数字数组转JSON时避免科学计数法JSON.toJSONString(tipIds, SerializerFeature.DisableCircularReferenceDetect);性能优化:对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);错误处理:若出现 Invalid JSON text 错误,检查:
JSON字符串是否包含未转义的特殊字符
数组括号是否匹配
对象键是否加双引号
版本兼容性:
MySQL 5.7.8+ 支持 JSON_CONTAINS
MySQL 8.0+ 推荐使用 JSON_TABLE 进行复杂查询
调试技巧:
// 先打印生成的SQL验证JSON格式System.out.println(wrapper.getCustomSqlSegment());// 手动执行SQL确认结果通过以上方法,可实现MyBatis Plus对MySQL JSON数组的高精度匹配,兼顾安全性与性能。实际开发中建议结合业务场景选择简单匹配或复杂路径查询。