Spring Boot 中如何处理存取 MySQL 中 JSON 类型的字段

请添加图片描述

👨🏻‍💻 热爱摄影的程序员
👨🏻‍🎨 喜欢编码的设计师
🧕🏻 擅长设计的剪辑师
🧑🏻‍🏫 一位高冷无情的全栈工程师
欢迎分享 / 收藏 / 赞 / 在看!

已知在 MySQL 中有表 test_json_type,定义如下:

-- 测试JsonType
drop table if exists test_json_type;
create table test_json_type
(
    test_id     bigint not null primary key comment 'testID',
    ids         json not null comment 'ids',
) engine innodb comment '测试JsonType表';

在 MyBatis-Plus 中,可以通过实现 TypeHandler 接口来创建自定义的类型处理器,用于处理 Java 类型和 JDBC 类型之间的转换。

为了处理 JSON 字符串和 Java 数组之间的转换,创建一个名为 JsonTypeHandler 的类,并实现 TypeHandler 接口,将 Java 中的字符串数组转换为 JSON 字符串存储到 MySQL 数据库中,以及将数据库中的 JSON 字符串转换回 Java 字符串数组。

MyBatis-Plus 官网-字段类型处理器

首先,需要添加 Jackson 库到项目中,因为我们将使用它来序列化和反序列化 JSON:

<!-- 添加Jackson依赖 -->  
<dependency>  
    <groupId>com.fasterxml.jackson.core</groupId>  
    <artifactId>jackson-databind</artifactId>  
    <version>2.13.0</version>  
</dependency>

然后,创建 JsonTypeHandler 类。使用 Jackson 库的 ObjectMapper 来执行 JSON 序列化和反序列化。setNonNullParameter 方法用于将 Java 数组转换为 JSON 字符串并设置到 PreparedStatement 中,而 getNullableResult 方法用于从 ResultSet 或 CallableStatement 中检索 JSON 字符串并转换回 Java 数组:

public class JsonTypeHandler<T> extends BaseTypeHandler<T> {  
  
    private static final ObjectMapper objectMapper = new ObjectMapper();  
  
    @Override  
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {  
        try {  
            if (parameter instanceof String[]) {  
                String json = objectMapper.writeValueAsString((String[]) parameter);  
                ps.setString(i, json);  
            } else {  
                throw new IllegalArgumentException("Cannot convert type " + parameter.getClass().getName() + " to JSON");  
            }  
        } catch (JsonProcessingException e) {  
            throw new RuntimeException("Error converting to JSON", e);  
        }  
    }  
  
    @Override  
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {  
        String json = rs.getString(columnName);  
        if (json != null) {  
            try {  
                return (T) objectMapper.readValue(json, String[].class);  
            } catch (IOException e) {  
                throw new RuntimeException("Error converting JSON to type", e);  
            }  
        }  
        return null;  
    }  
  
    @Override  
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {  
        String json = rs.getString(columnIndex);  
        if (json != null) {  
            try {  
                return (T) objectMapper.readValue(json, String[].class);  
            } catch (IOException e) {  
                throw new RuntimeException("Error converting JSON to type", e);  
            }  
        }  
        return null;  
    }  
  
    @Override  
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {  
        String json = cs.getString(columnIndex);  
        if (json != null) {  
            try {  
                return (T) objectMapper.readValue(json, String[].class);  
            } catch (IOException e) {  
                throw new RuntimeException("Error converting JSON to type", e);  
            }  
        }  
        return null;  
    }  
}

接下来,需要在 MyBatis 的映射文件或注解中指定使用这个自定义的类型处理器。如果使用 XML 映射文件,可以这样做:

<resultMap id="productResultMap" type="com.example.Product">  
    <id column="id" property="id"/>  
    <result column="spec_ids" property="specIds" typeHandler="com.example.JsonTypeHandler"/>  
    <!-- 其他字段映射 -->  
</resultMap>

如果使用注解,需在实体类开启映射 autoResultMap = true 并且在字段上使用 @TypeHandler 注解:

@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "test_json_type", autoResultMap = true)
public class TestJsonType extends BaseEntity {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * testID
     */
    @TableId(value = "test_id")
    private Long testId;

    /**
     * ids
     */
    @TableField(value = "ids", typeHandler = JsonTypeHandler.class)
    private String[] ids;
}

然后就可以正常地存取 JSON 类型的字段了:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

K8S部署Nginx与问题

【containerd错误解决系列】failed to create shim task, OCI runtime create failed, unable to retrieve OCI... 环境 # cat /etc/redhat-release CentOS Linux release 8.0.1905 (Core) # uname -r 4.18.0-348.rt7.130.el8.x86_64 问题及现象 1、pod的状态全部都是Conta…

谷粒商城实战(013 业务-认证服务-短信验证)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第211p-第p219的内容 介绍 认证中心要集成 社交登录、OAuth2.0、单点登录 等功能 OAuth 2.0&#xff1a; 问题解决&#xff1a; OAuth 2.0 主要…

鸿蒙应用开发之Web组件2

前面学习了加载Web组件,在使用这个组件之前需要设置网络加载的权限,否则是不能使用Web组件,所以大家在使用这个组件时,需要仔细检查是否有设置这个权限。 如果Web组件只是默认加载一次连接,就可以使用构造时传入的参数来决定,如果想不断地变换不同的网络地址,就需要使用…

「GO基础」在Windows上安装Go编译器并配置Golang开发环境

文章目录 1、安装Go语言编译程序1.1、下载GoLang编译器1.2、安装GoLang编译器 2、配置Golang IDE运行环境2.1、配置GO编译器2.1.1、GOROOT 概述2.1.2、GOROOT 作用2.1.2、配置 GOROOT 2.2、配置GO依赖管理2.2.1、Module管理依赖2.2.2、GOPATH 管理依赖 2.3、运行GO程序2.3.1、创…

05_数组和结构体

结构体 结构体的使用(重点) 结构体值传参 传值是指将参数的值拷贝一份传递给函数&#xff0c;函数内部对该参数的修改不会影响到原来的变量 结构体地址传递 传址是指将参数的地址传递给函数&#xff0c;函数内部可以通过该地址来访问原变量&#xff0c;并对其进行修改。…

大量excel文件私密性较强 需要密码保护 如何给excel文件批量加密

一&#xff0c;前言 在现代办公环境中&#xff0c;Excel文件已成为数据存储和交流的常见工具。然而&#xff0c;随着数据泄露和信息安全问题的日益严重&#xff0c;如何保护Excel文件的安全性成为了我们关注的焦点。批量加密Excel文件成为了一种有效的解决方案&#xff0c;它可…

【光伏行业】光伏发电的应用领域

光伏发电作为一种清洁、可再生的能源技术&#xff0c;在多个领域都有广泛的应用。以下是一些光伏发电的主要应用领域&#xff1a; 住宅和商业建筑&#xff1a;光伏板可以安装在屋顶上&#xff0c;为建筑提供电力。这不仅降低了对电网的依赖&#xff0c;还减少了电费支出&#x…

Spring (四) 之配置及配置文件的操作

文章目录 1、Spring 基于注解的配置基于注解的配置引入依赖包配置实体类数据访问层业务层业务层实现测试 2、Bean和Component和Configuration的区别1 Bean:2 Component:3 Configuration:总结&#xff1a; 区别Component和Configuration区别 3、Spring读取properties配置文件准备…

【C++】开始使用优先队列

送给大家一句话: 这世上本来就没有童话&#xff0c;微小的获得都需要付出莫大的努力。 – 简蔓 《巧克力色微凉青春》 开始使用优先队列 1 前言2 优先队列2.1 什么是优先队列2.2 使用手册2.3 仿函数 3 优先队列的实现3.1 基本框架3.2 插入操作3.3 删除操作3.4 其他函数 4 总结T…

【ZYNQ】PS和PL数据交互丨AXI总线(主机模块RTL代码实现)

文章目录 一、PS-PL数据交互桥梁&#xff1a;AXI总线1.1 AXI总线和AXI4总线协议1.2 PS-PL数据传输的主要场景1.2.1 PL通过AXI_HP操作DDR3 Controller读写DDR31.2.2 PS作主机使用GP接口传输数据 1.3 AXI端口带宽理论1.4 AXI 总线的读写分离机制1.5 握手机制1.6 AXI_Lite总线1.7 …

【软考】设计模式之命令模式

目录 1. 说明2. 应用场景3. 结构图4. 构成5. 优缺点5.1 优点5.2 缺点 6. 适用性7.java示例 1. 说明 1.命令模式&#xff08;Command Pattern&#xff09;是一种数据驱动的设计模式。2.属于行为型模式。3.请求以命令的形式被封装在对象中&#xff0c;并传递给调用对象。4.调用对…

制作直通网线和交叉网线

制作直通网线和交叉网线 1. 网络直通线2. 网络交叉线References 双绞线的连接方法有两种&#xff1a;直通连接和交叉连接 。 直通连接是将双绞线的两端分别都依次按白橙、橙、白绿、蓝、白蓝、绿、白棕、棕色的顺序 (国际 EIA/TIA 568B 标准) 压入 RJ45 水晶头内。这种方法制作…

剧本杀小程序:线上剧本杀成为行业必然趋势

剧本杀作为一个社交娱乐游戏方式&#xff0c;受到了年轻人的喜爱。剧本杀是一个新型的游戏方式&#xff0c;能够带大众带来新鲜感和刺激感&#xff0c;让玩家通过角色扮演进行游戏体验&#xff1b;并且剧本杀还具有较强的社交性&#xff0c;在当下快节奏生活下&#xff0c;以游…

【AI】在Windows10下部署本地LLM RAG服务

【背景】 上一篇介绍了如何用Ubuntu命令行部署ollama LLM+RAG服务。部署后等于拥有了基于内网的AI Saas服务,其它内网用户可以通过默认的网址访问Playground对AI进行问答。 【概念】 RAG:通过词向量技术,将文件内容向量化后,通过语言模型以自然交流的形式得到文本相关的…

MySQL表级锁——技术深度+1

引言 本文是对MySQL表级锁的学习&#xff0c;MySQL一直停留在会用的阶段&#xff0c;需要弄清楚锁和事务的原理并DEBUG查看。 PS:本文涉及到的表结构均可从https://github.com/WeiXiao-Hyy/blog中获取&#xff0c;欢迎Star&#xff01; MySQL表级锁 MySQL中表级锁主要有表锁…

【CAD建模号】学习笔记(三):图形绘制区1

图形绘制区介绍 CAD建模号的图形绘制区可以绘制我们所需要的各种3D模型&#xff0c;绘制的图形即为模型对象&#xff0c;包括线、面、体等。 1. 二维图形绘制组 二维图形是建模的基础&#xff0c;大多数复杂的模型都是基于二维图形制作出来的&#xff0c;掌握二维图形的绘制等…

png静图转换gif动图如何操作?轻松一键快速转换gif动图

想要把多张Png格式图片转换成gif格式动图时要怎么操作&#xff1f;图片常见的有静图和动图&#xff0c;而jpg、png、gif等是最常见的图片格式。想要把png格式图片转换成gif动画还不想下载任何软件的时候就可以使用gif制作工具。不需要下载软件在线就能操作。能够轻轻松松就能快…

uniapp开发之【上传图片上传文件】的功能

一、上传图片功能&#xff0b;图片回显点击图片预览&#xff1a; 是通过uview框架的u-upload进行开发的&#xff0c;先导入uview&#xff01; <template><view class""><!-- 按钮 --><view class"listBtn" click"uploadDesign()…

透过内核收包流程理解DPDK

前言 网络通信作为互联网的底座&#xff0c;其网络服务质量直接影响着用户的上网体验。如微信这类级别的应用&#xff0c;拥有上亿级别的日活&#xff0c;是典型的高并发的场景&#xff0c;简单的堆硬件无法有效的解决该类问题&#xff0c;提高单台服务器的性能成为问题的焦点…

百度文心一言与谷歌Gemini的对比

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 本文从多角度将百度文心一言与谷歌Gemini进行对比。因为不同评测基准的侧重点和难度可能有所不同&#xff0c;所以本文涉及到的评测结果仅供参考。Gemini和文心一言都是非常…