MySQL处理非结构化JSON数据(附 MyBatis-Plus 集成)

news2025/5/18 23:25:35

概述

MySQL 自5.7起开始支持JSON格式的非结构化数据,并且在8.x版本进行性能优化

关于 JSON

JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的 js 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

时下 JSON 使用访问非常广泛,大多 Web 接口都采用该格式。

MySQL 相关函数

详见:json-functions

说明

  1. 文档中的 json_doc 是值以字符串形式传递的 JSON 对象(通常用单引号包裹)

实践操作

建表

这里创建一个简单表,包含格式为 json 的字段value

CREATE TABLE `demo` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `t` varchar(100) DEFAULT NULL,
  `v` json DEFAULT NULL,
  `addOn` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

数据增删改查

新增数据

INSERT INTO demo (`t`, `v`) VALUES 
    ('0', '{"day":"2022-12-16", "value":"阴", "uid":"001","region":{"code":4500}}'),
    ('0', '{"day":"2022-12-16", "value":"阴", "uid":"002","region":{"code":4501}}'),
    ('0', '{"day":"2022-12-16", "value":"阳", "uid":"003","region":{"code":4500}}');

可以看到,JSON 类型的数据其实还是以字符串形式进行插入,此处需要注意 JSON 格式的字符串是强格式的(属性名必须是双引号,属性值如果是字符串也必须是双引号)。

再看看新增后的数据,发现对 Key 进行了排序(如下图)。
在这里插入图片描述

数据查询

/*平台字段查询*/
select * from demo where t='0';
/*
JSON 对象查询
-> 等价于 JSON_EXTRACT 函数
*/
select * from demo where t='0' and v->'$.value'='阴';
select * from demo where t='0' and JSON_EXTRACT(v, '$.value')='阴'
/*JSON 子对象查询*/
select * from demo where t='0' and v->'$.value'='阴' and v->'$.region.code'=4500;
select * from demo where t='0' and v->'$.value'='阴' and v->'$.region.code'>4500;

/*
如果不确定 JSON 对象查询 path 怎么写,可以用 JSON_SEARCH 函数

SELECT JSON_SEARCH('{"day":"2022-12-16", "value":"阴", "uid":"001","region":{"code":4500}}', 'one', '阴');

结果为 $.value
*/

path 语法

未来更好地理解查询 path ,官方有一段示例:

假设 JSON 对象为 [3, {"a": [5, 6], "b": 10}, [99, 100]]

路径
$[0]3
$[1]{“a”: [5, 6], “b”: 10}
$[2][99, 100]
$[3]NULL
$[1].a[5, 6]
$[1].a[1]6
$[1].b10
$[2][0]99

$[3] 指向不存在的第四个元素,故为 NULL

提取 JSON 内容

select t as `type`, v->'$.day' as day, v->'$.region.code' as region, v->'$.uid' as uid from demo;

select t as `type`, v->>'$.day' as day, v->'$.region.code' as region, v->>'$.uid' as uid from demo;

/* 
-> 与 ->> 的区别是,前者返回值带双引号,后者不带(与使用习惯一致)
结果如下

type|day         |region|uid  |
----+------------+------+-----+
0   |"2022-12-16"|4500  |"001"|
0   |"2022-12-16"|4501  |"002"|
0   |"2022-12-16"|4500  |"003"|

*/

排序

select t as `type`, v->>'$.day' as day, v->'$.region.code' as region, v->>'$.uid' as uid from demo order by region desc;

修改

官方提供如下函数来修改 JSON 对象:

函数名说明参数
JSON_SETreplaces values for paths that exist and adds values for paths that do not existjson_doc, path, val[, path, val] …
JSON_REPLACEadds new values but does not replace existing valuesjson_doc, path, val[, path, val] …
JSON_INSERTjson_doc, path, val[, path, val] …
JSON_REMOVEtakes a JSON document and one or more paths that specify values to be removed from the documentjson_doc, path[, path] …
/*修改 region.code 为 4501*/
update demo set v =JSON_SET(v, '$.region.code', 4501) where id=2;
/*向 region 子对象中插入 name 属性*/
update demo set v =JSON_INSERT(v, '$.region.name', "柳州") where id =2;

/**
最后的对象为
{
    "day": "2022-12-16",
    "uid": "002",
    "value": "阴",
    "region": {
        "code": 4501,
        "name": "柳州"
    }
}
*/

其实用官方的方法使用起来不是特别方便(组合修改比较麻烦),一般都是直接在代码中修改好对象,再转换为 JSON 字符串覆盖到相应的字段 😄

删除

与传统的操作一致

集成 MyBatis-Plus

此处使用kotlin进行示范

// 定义实体类,此处 autoResultMap 需要设置为 true (否则 TypeHandler 的 parse 无法正常被调用)
@TableName(autoResultMap = true)
class Demo {
    var id                  = 0
    var t                   = ""
    @TableField(typeHandler = JacksonTypeHandler::class, jdbcType = JdbcType.BLOB)
    var v                   = mapOf<String, Any>()
    var addOn:Timestamp?    = null
}

@Mapper
interface DemoMapper:BaseMapper<Demo>

 @Test
fun queryDemo(){
    // 使用 LambdaQueryChainWrapper
    LambdaQueryChainWrapper(demoMapper)
        .apply("v->'$.value'='阴'")
        .apply("v->'$.region.code'>4500")
        .list()
        .forEach { d-> println(JSON.toJSONString(d)) }

    // 使用 QueryWrapper
    demoMapper.selectList(
        QueryWrapper<Demo>()
            .apply("v->'$.value'='阴'")
            .apply("v->'$.region.code'>4500")
    ).forEach { d->
        println(JSON.toJSONString(d))
    }

    /*
    使用 SqlRunner(需要开启该功能)
    
    mybatis-plus:
        global-config:
        enable-sql-runner: true
        */
    SqlRunner.db()
        .selectList("select * from demo where t='0' and v->'$.value'='阴' and v->'$.region.code'>4500;")
        .forEach { d-> println(d) }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/94025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Cloud Alibaba

Spring Cloud Alibaba第五部分 第二代 Spring Cloud 核心组件&#xff08;SCA&#xff09;第 1 节 Nacos 服务注册和配置中心1.1 Nacos 介绍1.2 Nacos 单例服务部署1.3 微服务注册到Nacos1.4 负载均衡1.5 Nacos 数据模型&#xff08;领域模型&#xff09;1.6 Nacos 配置中心1.6…

智能家居DIY创意之智能灯泡

一、什么是智能灯 传统的灯泡是通过手动打开和关闭开关来工作。有时&#xff0c;它们可以通过声控、触控、红外等方式进行控制&#xff0c;或者带有调光开关&#xff0c;让用户调暗或调亮灯光。 智能灯泡内置有芯片和通信模块&#xff0c;可与手机、家庭智能助手、或其他智能…

水下潜航器的建模与控制

(线性系统理论大作业) 题目 水下潜器模型&#xff0c;可能是潜艇或者鱼雷等对象。一个主推进螺旋桨&#xff0c;前后两对水平陀翼&#xff0c;后面一对垂直陀翼。   潜器前进过程中&#xff0c;通过调节助推进螺旋桨推力&#xff0c;以及三对陀翼的角度变化&#xff0c;对潜…

paddle_gpu安装配置

paddle_gpu安装配置1.确认安装版本2. 安装相关文件2.1 下载与安装3.cuDNN下载及安装4.创建conda虚拟环境5.参考教程1.确认安装版本 操作系统&#xff1a;windows安装方式:condapython版本:python3.7CUDA版本&#xff1a;本人电脑版本【11.6.134】&#xff0c;低于此版本电脑都…

傻白入门芯片设计,盘点CPU业界的顶尖人才(十四)

这篇文章主要是针对现在CPU业界的顶尖人才&#xff0c;体现为以下几点&#xff1a;提出了革命性的技术路线&#xff0c;做出了杰出的产品&#xff0c;为公司做出重要贡献。按照当前供职情况&#xff0c;根据国际巨头所在公司分类&#xff0c;我主要收集了AMD&#xff0c;其余几…

【DevOps实战系列】第八章:详解Jenkins集成Docker私服Nexus3

个人亲自录制全套DevOps系列实战教程 &#xff1a;手把手教你玩转DevOps全栈技术 Jenkins集成Docker镜像仓库 docker私服已经搭建完毕&#xff0c;下边我们期望jenkins做的事是&#xff1a; ①通过git拉取代码②通过maven构建生成jar包③构建含有jar包的镜像④推送到docker仓库…

五问补盲(三) | 补盲激光雷达,敢不敢直面新的安全威胁?

作者 | 爱LiDAR的小飞哥 编辑 | 王博在激光雷达上车的热潮中&#xff0c;各家都在技术参数上进行着“你死我活”的拼杀。 那么&#xff0c;参数代表一切吗&#xff1f;举个例子&#xff0c;测距200米的激光雷达一定比测距150米的更好吗&#xff1f; 可以肯定地说&#xff0c;非…

JVM 之 AdaptiveSizePolicy 参数

AdaptiveSizePolicy 简介 AdaptiveSizePolicy(自适应大小策略) &#xff1a; JDK 1.8 默认使用 UseParallelGC 垃圾回收器&#xff0c;该垃圾回收器默认启动了 AdaptiveSizePolicy&#xff0c;会根据GC的情况自动计算计算 Eden、From 和 To 区的大小。 配置&#xff1a; 开启…

vue生命周期

vue的生命周期就是vue实例从创建到销毁的全过程&#xff0c;就是从开始创建、初始化数据、编译模版、挂载Dom、更新渲染、卸载等⼀系列过程&#xff0c;在这个过程中存在生命周期的钩子函数&#xff0c;我们可以在对应阶段添加实现自己的代码。 钩子函数&#xff08;共8个&…

智慧物流|Springboot+Vue+Nodejs实现智慧物流系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

Java如何读取输入

文章目录0.写在前面1.介绍2.举例3.写在最后0.写在前面 Java语言可以接收从键盘的输入&#xff0c;一般用来在调试的时候会用到&#xff0c;实际开发一般不用。 所以在此记录比较简单。 1.介绍 读取流程&#xff1a; 1.导入需要的工具包 2.构造一个“标准输入流”System.in关…

软件测试基础理论体系学习10-什么是本地化测试?本地化测试有哪些问题?本地化测试的重点是什么?

10-什么是本地化测试&#xff1f;本地化测试有哪些问题&#xff1f;本地化测试的重点是什么&#xff1f;1 本地化测试概述1.1软件本地化概念1.2 软件本地化工程1.3 软件本地化的重要性2 本地化测试翻译问题2.1 软件本地化不等于软件翻译2.2 软件本地化语言翻译技术2.2.1 翻译记…

K8s Service 负载均衡底层分析

当我们创建完 Pod 后&#xff0c;Pod 的 IP 与 Service IP 会自动分配&#xff0c;而 Pod IP 仅 K8s 集群内部访问&#xff0c;那 K8s 集群外部客户端又是如何访问 Pod 呢&#xff1f;看了官方相关文档&#xff0c;查询到是通过 Host 的 iptables&#xff08;即 K8s 集群节点的…

服务器多用户共享Anaconda

实验室最近买了台服务器&#xff0c;这篇Blog用来记载一下给ubuntu 20.04的服务器安装一个共享的anaconda的步骤。 安装Anaconda 首先去anaconda的官网下载linux的安装包&#xff0c;推送到服务上。然后进行安装&#xff1a; sudo bash ./Anaconda3-2022.10-Linux-x86_64.sh…

99.(leaflet之家)leaflet军事标绘-分队战斗行动修改

地图之家总目录(订阅之前请先查看该博客) 地图之家:cesium+leaflet+echart+地图数据+地图工具等相关内容的介绍 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 下面献上完整代码,代码重要位置会做相应解释 <!DOCTYPE html> …

Linux从入门到进阶学习(Ⅰ):Linux系统安装与配置

目录 1 Linux概述 2 虚拟机安装 3 安装Centos系统 ​4 远程连接Linux系统 5 WSL环境 6 虚拟机快照 1 Linux概述 内核是操作系统的核心&#xff0c;Linux内核是免费开源的&#xff0c;由此产生了许多Linux发行版&#xff0c;包括&#xff1a;Ubuntu、CentOs等 2 虚拟机安…

零钱通项目(面向过程)

目录 项目需求 项目界面 思路 写代码 第一步 第二步 第三步 IDEA运行问题 日期问题 代码运行问题 第四步 第五步 第一种 第二种 第六步 第七步 完整代码 运行效果 项目需求 使用Java 开发 零钱通项目&#xff0c;可以完成收益入账&#xff0c;消费&#xff0…

SSH连接到GitHub的方法

前言 习惯了使用公司内的GitLab&#xff0c;已经有一段时间没有使用GitHub来维护自己的项目&#xff0c;近期需要新建个人项目在阿里云服务器上使用&#xff0c;竟然一时忘记了怎么用SSH连接GitHub。 因此本文记录一下SSH连接GitHub的方法&#xff0c;也方便后面自己参考。 整…

微服务框架 SpringCloud微服务架构 多级缓存 48 多级缓存 48.4 查询Tomcat【环境准备】

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 多级缓存 文章目录微服务框架多级缓存48 多级缓存48.4 查询Tomcat【环境准备】48.4.1 多级缓存需求48 多级缓存 48.4 查询Tomcat【环境准备…

springMVC+mysql实现的Java web医院分诊挂号管理系统源码附带论文及视频指导运行教程

今天给大家演示的是一款由springMVCmysql实现的Java web医院分诊挂号管理系统&#xff0c;主要实现了患者管理、科室管理、挂号管理等业务功能&#xff0c;此外系统还有角色权限管理&#xff0c;用户管理、菜单管理、定时任务管理等功能&#xff0c;这些功能对于想要二次开发的…