当前位置: 首页 > 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…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法

使用 ROS1-Noetic 和 mavros v1.20.1&#xff0c; 携带经纬度海拔的话题主要有三个&#xff1a; /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码&#xff0c;来分析他们的发布过程。发现前两个话题都对应了同一…...