当前位置: 首页 > news >正文

存储或读取时转换JSON数据

一、 数据库类型

在这里插入图片描述

二、使用Hutool工具

存储时将数据转换为JSON数据

在这里插入图片描述

获取时将JSON数据转换为对象

在这里插入图片描述

发现问题:

原本数据对象是AddressFirend但是转换完成后数据变成了JSONArray和JSONObject
在这里插入图片描述

三、自定义TypeHandler继承Mybatis的BaseTypeHandler处理器
package com.jiusi.config;import cn.hutool.json.JSONUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class jsonTypeHandler01<T> extends BaseTypeHandler {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {//将数据转换为json字符串ps.setString(i, JSONUtil.toJsonStr(parameter));}@Overridepublic T getNullableResult(ResultSet rs, String columnName) throws SQLException {//将json字符串转换为任意类型if(rs.getString(columnName).charAt(0)=='{'){return (T) JSONUtil.parseObj(rs.getString(columnName));}return (T)JSONUtil.parseArray(rs.getString(columnName));}@Overridepublic T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return null;}@Overridepublic T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return null;}
}

在xml中使用

添加数据时在需要改变的字段后添加TypeHandler属性,使用自定义的JsonTypeHandler

    <insert id="insert">insert into msg (name, age, height, address, friend)values (#{name}, #{age}, #{height}, #{address,typeHandler=com.jiusi.config.jsonTypeHandler},#{friend,typeHandler=com.jiusi.config.jsonTypeHandler})</insert>

获取数据时在ResultMap里Result上添加typeHandler属性,同样使用自定义的JackonTypeHandler

    <resultMap type="com.jiusi.model.Msg" id="Jackon"><result property="id" column="id"></result><result property="name" column="name"></result><result property="age" column="age"></result><result property="height" column="height"></result><result property="address" column="address" typeHandler="com.jiusi.config.JackonTypeHandler">				</result><result property="friend" column="friend" typeHandler="com.jiusi.config.JackonTypeHandler"></result></resultMap>

但是查询出来的同样是JSONArray和HJSONObject
在这里插入图片描述

为什么使用BaseTypeHandler 而不是 TypeHandler

BaseTypeHandler<T>是一个实现了TypeHandler接口的抽象基类,提供了对TypeHandler接口的一些基础实现和默认行为,简化了自定义类型处理器的开发。通过继承BaseTypeHandler,开发者只需要关注具体的转换逻辑,而无需重复实现所有接口方法。
在这里插入图片描述

四、结合Redis进行转换

往数据库存储数据的同时将全类名也存入进去

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
package com.jiusi.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class jsonTypeHandler02<T> extends BaseTypeHandler<T> {Jackson2JsonRedisSerializer<Object> serializer;// 解决序列化乱码问题public jsonTypeHandler02() {       // 指定序列化输入的类型, 即输入到redis的类型serializer = new Jackson2JsonRedisSerializer<>(Object.class);// 指定序列化输出的类型ObjectMapper objectMapper = new ObjectMapper();//JsonAutoDetect.Visibility.ANY 代表所有属性或字段都可以序列化objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);//新版用法//以数组的方式存放到Redis,Class Type 全类名作为为第一个元素,Json字符串为第二个元素。objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);}@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {//将参数序列化为byts数组然后转成字符串ps.setString(i,new String( serializer.serialize(parameter)));}@Overridepublic T getNullableResult(ResultSet rs, String columnName) throws SQLException {//  将字符串反序列化为对象return (T) serializer.deserialize(rs.getString(columnName).getBytes(StandardCharsets.UTF_8));}@Overridepublic T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return null;}@Overridepublic T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return null;}}

将xml中的typeHandler 修改成当前处理器

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

五、自定义序列化方式

与Redis一样将全类名同时存入数据库

package com.jiusi.config;import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;/*** 自定义序列化方式* @param <T>*/
public class MybatisToJsonConfig<T> {static {DEFAULT_CHARSET = StandardCharsets.UTF_8;}public static final Charset DEFAULT_CHARSET;private final JavaType javaType;private ObjectMapper objectMapper = new ObjectMapper();public MybatisToJsonConfig(Class<T> type) {this.javaType = this.getJavaType(type);}public MybatisToJsonConfig(JavaType javaType) {this.javaType = javaType;}public T deserialize(@Nullable byte[] bytes) throws Exception {try {return this.objectMapper.readValue(bytes, 0, bytes.length, this.javaType);} catch (Exception ex) {throw new Exception("无法读取JSON: " + ex.getMessage(), ex);}}public byte[] serialize(@Nullable Object t) throws Exception {try {return this.objectMapper.writeValueAsBytes(t);} catch (Exception ex) {throw new Exception("无法写入JSON: " + ex.getMessage(), ex);}}public void setObjectMapper(ObjectMapper objectMapper) {Assert.notNull(objectMapper, "'objectMapper' 不能为空");this.objectMapper = objectMapper;}private JavaType getJavaType(Class<?> clazz) {return TypeFactory.defaultInstance().constructType(clazz);}}
package com.jiusi.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** 同样继承BaseTypeHandler但是序列化方式是使用自定义序列化方式* @param <T>*/
public class JsonTypeHandler03<T> extends BaseTypeHandler<T> {private static MybatisToJsonConfig<Object> serializer;static {serializer = new MybatisToJsonConfig<>(Object.class);ObjectMapper objectMapper = new ObjectMapper();//JsonAutoDetect.Visibility.ANY 代表所有属性或字段都可以序列化objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);//以数组的方式存放到Redis,Class Type 全类名作为为第一个元素,Json字符串为第二个元素。objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);serializer.setObjectMapper(objectMapper);}@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {//使用Redis的序列化将参数序列化为byts数组然后转成字符串try {ps.setString(i,new String( serializer.serialize(parameter)));} catch (Exception e) {e.printStackTrace();}}@Overridepublic T getNullableResult(ResultSet rs, String columnName) throws SQLException {//  是使用自定义的Redis反序列化将字符串反序列化为对象try {return (T) serializer.deserialize(rs.getString(columnName).getBytes(StandardCharsets.UTF_8));} catch (Exception e) {e.printStackTrace();}return null;}@Overridepublic T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return null;}@Overridepublic T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return null;}}

将xml中的typeHandler 修改成当前处理器
在这里插入图片描述

在这里插入图片描述

六、Mybatis-Plus

使用Mybatis-Plus同样可以只需要只需要加两个注解在类上添加@TableName(Value = “表名” , autoResultMap = true),并且在需要转换的字段上添加@TableField( typeHandler = 处理器)

处理器可以使用上面我们自定义的处理器

在这里插入图片描述

相关文章:

存储或读取时转换JSON数据

一、 数据库类型 二、使用Hutool工具 存储时将数据转换为JSON数据 获取时将JSON数据转换为对象 发现问题&#xff1a; 原本数据对象是Address 和 Firend但是转换完成后数据变成了JSONArray和JSONObject 三、自定义TypeHandler继承Mybatis的BaseTypeHandler处理器 package …...

Spring Data JPA的作用和用法

Spring Data JPA 是 Spring 框架的一个模块&#xff0c;它提供了一种数据访问抽象&#xff0c;允许以一种声明式和简洁的方式来处理数据库操作。它基于 Java Persistence API (JPA)&#xff0c;是一个行业标准的 ORM&#xff08;对象关系映射&#xff09;规范&#xff0c;用于将…...

【go项目01_学习记录08】

学习记录 1 模板文件1.1 articlesStoreHandler() 使用模板文件1.2 统一模板 1 模板文件 重构 articlesCreateHandler() 和 articlesStoreHandler() 函数&#xff0c;将 HTML 抽离并放置于独立的模板文件中。 1.1 articlesStoreHandler() 使用模板文件 . . . func articlesSt…...

Java中的线程

一、创建线程的几种方式&#xff1f; ① 通过继承Thread类并重写run方法 &#xff0c;实现简单但不可以继承其他类 Thread底层也是实现了Runnable接口&#xff0c;重写的是run而不是start方法 ②实现Runnable接口并重写run方法&#xff0c; 避免了单继承的局限性&#xff…...

顺序表的实现(迈入数据结构的大门)(完整代码)

seqlist.h #pragma once typedef int SLDataType;#include<stdio.h> #include<stdlib.h> #include<assert.h>typedef struct SeqList {SLDataType* a;int size; // 有效数据个数int capacity; // 空间容量 }SL;//初始化和销毁 void SLInit(SL* ps); void SL…...

neo4j-5.11.0安装APOC插件or配置允许使用过程的权限

在已经安装好neo4j和jdk的情况下安装apoc组件&#xff0c;之前使用neo4j-community-4.4.30&#xff0c;可以找到配置apoc-4.4.0.22-all.jar&#xff0c;但是高版本neo4j对应没有apoc-X.X.X-all.jar。解决如下所示&#xff1a; 1.安装好JDK与neo4j 已经安装对应版本的JDK 17.0…...

mybatis 中 #{}和 ${}的区别是什么?

在 MyBatis 中&#xff0c;#{} 和 ${} 是两种用于参数替换的语法&#xff0c;但它们之间存在一些重要的区别&#xff0c;主要体现在安全性、预编译和动态 SQL 上。 安全性&#xff1a; #{}&#xff1a;这是预编译处理&#xff0c;MyBatis 会为传入的参数生成 PreparedStatement…...

深入解析C#中的接口设计原则

深入解析C#中的接口设计原则 目录 深入解析C#中的接口设计原则 一、接口设计的SOLID原则 二、接口设计的最佳实践 三、接口设计的高级技术 四、结论 接口在面向对象编程中扮演着至关重要的角色。它们是定义行为契约的一种方式&#xff0c;允许实现者提供这些行为的具体实现…...

106短信群发平台在金融和法务行业的应用分析

一、金融行业应用 1.客户通知与提醒&#xff1a;银行、证券、保险等金融机构经常需要向客户发送各类通知和提醒&#xff0c;如账户余额变动、交易确认、扣费通知、理财产品到期提醒等。106短信群发平台可以快速、准确地将这些信息发送到客户的手机上&#xff0c;确保客户及时获…...

Spring AOP(2)

目录 Spring AOP详解 PointCut 切面优先级Order 切点表达式 execution表达式 切点表达式示例 annotation 自定义注解MyAspect 切面类 添加自定义注解 Spring AOP详解 PointCut 上面代码存在一个问题, 就是对于excution(* com.example.demo.controller.*.*(..))的大量重…...

Spring-依赖注入的处理过程

前置知识 1 入口 DefaultListableBeanFactory#resolveDependency 2 每个依赖都有对应的DependencyDescriptor 3 自定绑定候选对象处理器AutowireCapableBeanFactory 注入处理 我们可以看到接口AutowireCapableBeanFactory中有两个方法。 第一个是单个注入&#xff1a; Null…...

2.用python爬取的保存在text文件中的格式为MP4的视频url

文章目录 一、url的保存格式二、MP4视频获取 一、url的保存格式 爬取的视频名字和url保存在text文件中&#xff0c;每一个视频都是一个单独的text&#xff0c;其中text的文件名就是视频的名字&#xff0c;text内容是视频的下载url&#xff0c;并且所有的text都保存在同一个文件…...

Java基于B/S医院绩效考核管理平台系统源码java+springboot+MySQL医院智慧绩效管理系统源码

Java基于B/S医院绩效考核管理平台系统源码javaspringbootMySQL医院智慧绩效管理系统源码 医院绩效考核系统是一个关键的管理工具&#xff0c;旨在评估和优化医院内部各部门、科室和员工的绩效。一个有效的绩效考核系统不仅能帮助医院实现其战略目标&#xff0c;还能提升医疗服…...

UE 蓝图堆栈调试

蓝图打断点后如果想查看断点前的执行逻辑&#xff0c;Tools→Debug→BlueprintDebugger 然后打断点运行&#xff0c;执行顺序是从下往上...

UE4_摄像机_使用摄像机的技巧

学习笔记&#xff0c;不喜勿喷&#xff01;祝愿生活越来越好&#xff01; 知识点&#xff1a; a.相机跟随。 b.相机抖动。 c.摄像机移动 d.四元数插值&#xff08;保证正确旋转方向&#xff09;。 e.相机注视跟踪。 1、新建关卡序列&#xff0c;并给小车添加动画。 2、创…...

ssm115乐购游戏商城系统+vue

毕业生学历证明系统 设计与实现 内容摘要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统毕业生学历信息管理难…...

【可实战】被测需求理解(需求文档是啥样的、从哪些角度进行需求评审、需求分析需要分析出哪些内容、如何提高需求分析能力)

产品人员会产出一个需求文档&#xff0c;然后组织一个需求的宣讲。测试人员的任务就是在需求宣讲当中&#xff0c;分析需求有没有存在一些问题&#xff0c;然后在需求宣讲结束之后通过分析需求文档&#xff0c;分析里面的测试点并预估一个排期。 一、需求文档是什么样的&#x…...

伪类和伪元素的区别是什么?

一、两者的定义 1.伪类&#xff08;pseudo-class&#xff09;是一个以冒号作为前缀&#xff0c;被添加到一个选择器末尾的关键字&#xff0c;当你希望样式在特定状态才被呈现到指定的元素时&#xff0c;你可以往元素的选择器后面加上对应的伪类。 2.伪元素用于创建一些不在文档…...

gorm-sharding分表插件升级版

代码地址&#xff1a; GitHub - 137/gorm-sharding: Sharding 是一个高性能的 Gorm 分表中间件。它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充&#xff0c;带来的额外开销极小。对开发者友好、透明&#xff0c;使用上与普通 SQL、Gorm 查询无差别.解决了原生s…...

MoviePy(Python音视频开发)

音视频基础帧率、码率、分辨率视频格式H.264和H.265视频压缩算法 Moviepy常见剪辑类VideoFlieClipImageFlieClipColorClipTextClipCompositeVideoClipAudioFlieClipCompositeAudioClip 常见操作音视频的读入与导出截取音视频 音视频基础 帧率、码率、分辨率 体积&#xff08;V…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...