百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

MySql中json类型数据的查询以及在MyBatis-Plus中的使用

csdh11 2025-01-02 15:30 137 浏览

表结构和初始数据

  • 新建表结构
CREATE TABLE `json_test` (
  `id` int NOT NULL AUTO_INCREMENT,
  `roles` json DEFAULT NULL COMMENT '角色',
  `project` json DEFAULT NULL COMMENT '项目',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
  • 初始数据
INSERT INTO `ctts_dev`.`json_test`(`id`, `roles`, `project`) VALUES (1, '[{"id": 10001, "name": "管理员"}, {"id": 10002, "name": "开发"}, {"id": 10003, "name": "测试"}]', '{"id": 11111, "name": "项目1"}');
INSERT INTO `ctts_dev`.`json_test`(`id`, `roles`, `project`) VALUES (2, '[{"id": 10002, "name": "开发"}]', '{"id": 22222, "name": "项目2"}');
INSERT INTO `ctts_dev`.`json_test`(`id`, `roles`, `project`) VALUES (3, '[{"id": 10003, "name": "测试"}]', '{"id": 11111, "name": "项目1"}');



其中 roles 字段存的是 数组

[{"id":10001,"name":"管理员"},{"id":10002,"name":"开发"},{"id":10003,"name":"测试"}]

project 存的是 对象

{"id": 11111, "name": "项目1"}

对象JSON查询

查询 project项目1 的(精准查询)

  • 使用箭头函数
SELECT * FROM json_test 
WHERE project -> '$.name' = '项目1'
  • 使用 JSON_CONTAINS
SELECT * FROM json_test 
WHERE JSON_CONTAINS(project, JSON_OBJECT('name', '项目1'))

模糊查询 project 字段

SELECT * FROM json_test 
WHERE project -> '$.name' like '%项目%'

数组JSON查询

查询 roles 中包含 测试 的(精准查询)

SELECT * FROM json_test 
WHERE JSON_CONTAINS(roles,JSON_OBJECT('name','测试'))

模糊查询 roles 字段

SELECT * FROM json_test
WHERE roles -> '$[*].name' like '%测%'

其中,中括号里的 星号 ,也可以替换为数组中的下标index

SELECT * FROM json_test
WHERE roles -> '$[1].name' like '%测%'

这样就是模糊查询在数组中第二个元素是否含有 字的,

提取JSON中数据

提取 json 中单个字段的值

SELECT
    id,
    roles -> '$[*].name' AS roleName,
    project ->> '$.name' AS projectName 
FROM
    json_test

也提供了 JSON_EXTRACT 函数,结果和上面是一样的,只是查询出的 projectName 是带双引号的

SELECT
    id,
    JSON_EXTRACT( roles, '$[*].name' ) AS roleName,
    JSON_EXTRACT( project, '$.name' ) AS projectName 
FROM
    json_test



如果不需要双引号,可以使用 JSON_UNQUOTE 函数

提取 json 中所有字段的值,用 星号 就行

SELECT
    id,
    roles -> '$[*].*' AS roleName,
    project ->> '$.*' AS projectName 
FROM
    json_test

一个箭头和两个箭头的区别

MySql中箭头函数,一个箭头和两个箭头的区别

如果是字符串,一个箭头返回的结果是带双引号的(只针对字符串),两个箭头是不带的

SELECT project -> '$.name' as projectName FROM json_test;
"项目1"
"项目2"
"项目1"

SELECT project ->> '$.name' as projectName FROM json_test;
项目1
项目2
项目1

JSON_UNQUOTE 函数也是去掉双引号,等价于使用两个箭头

SELECT project ->> '$.name' as projectName FROM json_test
等价于
SELECT JSON_UNQUOTE(project -> '$.name') as projectName FROM json_test
等价于
SELECT JSON_UNQUOTE(JSON_EXTRACT(project, '$.name')) as projectName FROM json_test

可以看出还是箭头函数方便

复杂JSON

多层复杂的 json 结构,提取想要的数据,也只需要按照key点下去即可

{
    "status": 1,
    "message": "SUCCESS",
    "data": {
        "list": [
            {
                "id": "1565510388254765086",
                "name": "测试1111",
                "object": [
                    {
                        "id": "1565510583118209025",
                        "tenderName": "客户1"
                    }
                ]
            },
            {
                "id": "1565504356392558665",
                "name": "测试2222",
                "object": [
                    {
                        "id": "1565504633934229506",
                        "tenderName": "客户2"
                    }
                ]
            }
        ]
    }
}
SELECT other ->> '$.data.list[*].contractObject' 
FROM json_test 

- other 为表字段名

如果不知道 key,也可以用 星号 代替,但是也要知道是在第几层

SELECT other ->> '$**.contractObject' 
FROM json_test 

在LambdaQueryChainWrapper中使用

MyBatis-Plus 中 使用 LambdaQueryChainWrapper 模糊查询 json 数据

new LambdaQueryChainWrapper<>(baseMapper)
                .like(StringUtils.isNotBlank(req.getTitle()), Test::getTitle, req.getTitle())
                .apply(StringUtils.isNotBlank(req.getRoles()), "roles ->> '$[*].name' LIKE CONCAT('%',{0},'%')", req.getRoles())
                .apply(StringUtils.isNotBlank(req.getProject()), "project -> '$.name' LIKE CONCAT('%',{0},'%')", req.getProject())
                .eq(req.getDeleted() != null, Test::getDeleted, req.getDeleted())
                .orderByDesc(Test::getCreatedAt)
                .list();

使用 LambdaQueryChainWrapper 准确查询 json 数据

new LambdaQueryChainWrapper<>(baseMapper)
                .apply(StringUtils.isNotBlank(req.getRoles()), "JSON_CONTAINS(roles, JSON_OBJECT('name',{0}))", req.getRoles())
                .apply(StringUtils.isNotBlank(req.getProject()), "project -> '$.name' = {0}", req.getProject())
                .orderByDesc(Test::getCreatedAt)
                .list();

使用 LambdaQueryChainWrapper 的话 ,一般都是用 apply 拼接自定义 sql

apply 是可以通过占位符的形式,传入多个参数的,也比较方便



LambdaQueryChainWrapper select 提取JSON数据

apply 是用做数据筛选用,那如果想 select 提取 json 中的数据呢

  • 首先需要在对应的实体类里新增一个字段,比如 roleName (不需要在表中创建该字段)
@TableField(value = "roles ->> '$[*].name'",
        insertStrategy = FieldStrategy.NEVER,
        updateStrategy = FieldStrategy.NEVER,
        select = false)
private String roleName;

其中,value 对应的就是 select xxxx 形式

insertStrategy = FieldStrategy.NEVER 不执行插入

updateStrategy = FieldStrategy.NEVER 不执行更新

select = false 不让该字段出现在 select

上述3个配置是为了不影响已有的增删改查,因为只是在实体类中新增了字段,没有在对应的表中增加该字段,可以根据自己的实际需求配置

  • 然后就可以在 LambdaQueryChainWrapper 中使用了
new LambdaQueryChainWrapper<>(baseMapper)
        .select(Test::getRoleName)
        .list();

对应执行的 sql 如下

SELECT roles ->> '$[*].name' AS roleName FROM json_test

这种方法可以在 select 中用 MySql 里的函数,比如常用的 SUM、MAX、COUNT

@TableField(value = "SUM(money)",
        insertStrategy = FieldStrategy.NEVER,
        updateStrategy = FieldStrategy.NEVER,
        select = false)
private BigDecimal moneyCount;

哎,就是不想在xml中写sql...(小声bb)

相关推荐

Github霸榜的SpringBoot全套学习教程,从入门到实战,内容超详细

前言...

SpringBoot+LayUI后台管理系统开发脚手架

源码获取方式:关注,转发之后私信回复【源码】即可免费获取到!项目简介本项目本着避免重复造轮子的原则,建立一套快速开发JavaWEB项目(springboot-mini),能满足大部分后台管理系统基础开...

Spring Boot+Vue全栈开发实战,中文版高清PDF资源

SpringBoot+Vue全栈开发实战,中文高清PDF资源,需要的可以私我:)SpringBoot致力于简化开发配置并为企业级开发提供一系列非业务性功能,而Vue则采用数据驱动视图的方式将程序...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础...

探秘Spring Cache:让Java应用飞起来的秘密武器

探秘SpringCache:让Java应用飞起来的秘密武器在当今快节奏的软件开发环境中,性能优化显得尤为重要。SpringCache作为Spring框架的一部分,为我们提供了强大的缓存管理能力,让...

3,从零开始搭建SSHM开发框架(集成Spring MVC)

目录本专题博客已共享在(这个可能会更新的稍微一些)https://code.csdn.net/yangwei19680827/maven_sshm_blog...

Spring Boot中如何使用缓存?超简单

SpringBoot中的缓存可以减少从数据库重复获取数据或执行昂贵计算的需要,从而显著提高应用程序的性能。SpringBoot提供了与各种缓存提供程序的集成,您可以在应用程序中轻松配置和使用缓...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

1,从零开始搭建SSHM开发框架(环境准备)

目录本专题博客已共享在https://code.csdn.net/yangwei19680827/maven_sshm_blog1,从零开始搭建SSHM开发框架(环境准备)...

做一个适合二次开发的低代码平台,把程序员从curd中解脱出来-1

干程序员也有好长时间了,大多数时间都是在做curd。现在想做一个通用的curd平台直接将我们解放出来;把核心放在业务处理中。用过代码生成器,在数据表设计好之后使用它就可以生成需要的controller...

设计一个高性能Java Web框架(java做网站的框架)

设计一个高性能JavaWeb框架在当今互联网高速发展的时代,构建高性能的JavaWeb框架对于提升用户体验至关重要。本文将从多个角度探讨如何设计这样一个框架,让我们一起进入这段充满挑战和乐趣的旅程...

【推荐】强&amp;牛!一款开源免费的功能强大的代码生成器系统!

今天,给大家推荐一个代码生成器系统项目,这个项目目前收获了5.3KStar,个人觉得不错,值得拿出来和大家分享下。这是我目前见过最好的代码生成器系统项目。功能完整,代码结构清晰。...

Java面试题及答案总结(2025版持续更新)

大家好,我是Java面试分享最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试场景题及答案。...

Java开发网站架构演变过程-从单体应用到微服务架构详解

Java开发网站架构演变过程,到目前为止,大致分为5个阶段,分别为单体架构、集群架构、分布式架构、SOA架构和微服务架构。下面玄武老师来给大家详细介绍下这5种架构模式的发展背景、各自优缺点以及涉及到的...

本地缓存GuavaCache(一)(guava本地缓存原理)

在并发量、吞吐量越来越大的情况下往往是离不开缓存的,使用缓存能减轻数据库的压力,临时存储数据。根据不同的场景选择不同的缓存,分布式缓存有Redis,Memcached、Tair、EVCache、Aer...