存储或读取时转换JSON数据

news2025/1/10 21:01:55
一、 数据库类型

在这里插入图片描述

二、使用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 {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        //将数据转换为json字符串
        ps.setString(i, JSONUtil.toJsonStr(parameter));
    }

    @Override
    public 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));
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return null;
    }

    @Override
    public 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);
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        //将参数序列化为byts数组然后转成字符串
        ps.setString(i,new String( serializer.serialize(parameter)));
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        //  将字符串反序列化为对象
        return (T) serializer.deserialize(rs.getString(columnName).getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return null;
    }

    @Override
    public 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);
    }


    @Override
    public 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();
        }
    }

    @Override
    public 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;
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return null;
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }

}

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

在这里插入图片描述

六、Mybatis-Plus

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

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

在这里插入图片描述

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

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

相关文章

javaMail快速部署——发邮件喽~

目录 功能阐述 前序步骤 &#xff08;1&#xff09;到QQ邮箱中获取到授权码 代码实现 坑 今天在写一个修改密码的功能的时候要用到邮箱的发送&#xff0c;然后因为这个项目比较老旧了&#xff0c;采用的是javaWeb和jsp的配置&#xff0c;对于我只使用过springBoot整合的ja…

进一步分析并彻底解决 Flink container exit 143 问题

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

ASP.NET信息安全研究所设备管理系统的设计与实现

摘 要 以研究所的设备管理系统为背景&#xff0c;以研究所设备管理模式为研究对象&#xff0c;开发了设备管理系统。设备管理系统是设备管理与计算机技术相结合的产物&#xff0c;根据系统的功能需求分析与定义的数据模式&#xff0c;分析了应用程序的主要功能和系统实现的主…

最佳实践 | 八爪鱼采集器如何用PartnerShare做全民分销?

在数字化时代&#xff0c;数据采集和分析已经成为企业运营和决策的重要一环。八爪鱼采集器作为一款领先的SaaS产品&#xff0c;凭借其强大的数据采集和处理能力&#xff0c;成为了众多企业和个人用户的心头好。为了进一步拓展市场份额&#xff0c;提升品牌影响力&#xff0c;八…

nature《自然》期刊文献怎么在家查看下载

nature《自然》期刊我们都知道&#xff0c;是世界上历史悠久的、最有名望的科学杂志之一。下载该期刊文献是需要使用权限的&#xff0c;如果你没有nature《自然》期刊的资源&#xff0c;又该如何获取呢&#xff1f;请看本文的经验分享。 一、先百度“文献党下载器” 在文献党下…

PSCA电源管理软件栈示例

安全之安全(security)博客目录导读 目录 1、移动通讯系统 2、基础设施系统 本博客就PSCA电源管理软件栈进行举例&#xff0c;主要以移动通讯系统和基础设施系统为例来说明。 1、移动通讯系统 图3.4显示了一个可以在基于Linux的移动设备中实现的电源管理堆栈示例。 在Linux…

在uniapp中如何安装axios并解决跨域问题

目录 1、安装axios 2、导入 3、使用&#xff08;发请求&#xff09; 2.解决跨域问题 1.为什么要解决跨域问题&#xff1f; 2.前端如何解决跨域问题&#xff1f; 1、安装axios npm install axios 2、导入 在main.js中导入使用 import axios from axios; // 创建一个名…

【C++】STL-list模拟实现

目录 1、本次需要实现的3个类即接口总览 2、list的模拟实现 2.1 链表结点的设置以及初始化 2.2 链表的迭代器 2.3 容量接口及默认成员函数 1、本次需要实现的3个类即接口总览 #pragma once #include<iostream> #include<assert.h> using namespace std; templ…

机器学习算法之KNN分类算法【附python实现代码!可运行】

一、简介 在机器学习中&#xff0c;KNN&#xff08;k-Nearest Neighbors&#xff09;分类算法是一种简单且有效的监督学习算法&#xff0c;主要用于分类问题。KNN算法的基本思想是&#xff1a;在特征空间中&#xff0c;如果一个样本在特征空间中的k个最相邻的样本中的大多数属…

每日Attention学习5——Multi-Scale Channel Attention Module

模块出处 [link] [code] [WACV 21] Attentional Feature Fusion 模块名称 Multi-Scale Channel Attention Module (MS-CAM) 模块作用 通道注意力 模块结构 模块代码 import torch import torch.nn as nnclass MS_CAM(nn.Module):def __init__(self, channels64, r4):super(…

Android NDK开发——Android Studio 3.5.2安装与配置踩坑

Android NDK开发——Android Studio 3.5.2安装与配置踩坑 一、Android Studio下载二、配置踩坑报错1&#xff1a;Failed to install the following Android SDK packages as some licences have not been accepted报错2&#xff1a;No toolchains found in the NDK toolchains …

【全开源】Java上门洗车小程序源码上门洗车APP 小程序源码支持二次开发6.0

功能特点&#xff1a; 跨界创新&#xff1a;融入科技元素&#xff0c;借助移动互联网快速发展&#xff0c;将科技引入到传统洗车业中。 科技赋能&#xff1a;具有智能化的特点&#xff0c;用户可以根据自身的需求选择不同的洗车项目和服务&#xff0c;包括洗车的时间、地点和服…

滥用 Kubernetes 资源登上月球

Sysdig 2024 年云原生安全和使用报告强调了不断变化的威胁形势&#xff0c;但更重要的是&#xff0c;随着容器和 Kubernetes 等云原生技术的采用不断增加&#xff0c;并非所有组织都遵循最佳实践。当攻击者在 Kubernetes 等操作中利用容器来利用资源时&#xff0c;这最终会给攻…

【stomp 实战】spring websocket 接收消息源码分析

后台消息的发送过程&#xff0c;我们通过spring websocket用户消息发送源码分析已经了解了。我们再来分析一下后端接收消息的过程。这个过程和后端发送消息过程有点类似。 前端发送消息 前端发送消息给服务端的示例如下&#xff1a; 发送给目的/app/echo一个消息。 //主动发…

线程安全的概念及原因

1.观察线程不安全 public class ThreadDemo {static class Counter {public int count 0;void increase() {count;}}public static void main(String[] args) throws InterruptedException {final Counter counter new Counter();Thread t1 new Thread(() -> {for (int …

ES:聚合查询语法

基础查询结构&#xff1a; GET http://ip:prot/textbook/_search { "query" : { ...query子句... }, "aggs" : { "agg_name":{ "agg_type": { "agg_arg": agg_arg_value } } }, "sort" : { ..sor…

Cesium--加载天地图

背景&#xff1a;vue-admin-temlate cesium 天地图 天地图地址&#xff1a;国家地理信息公共服务平台 天地图 步骤一&#xff1a;申请成为天地图开发者&#xff0c;创建应用 1,天地图使用方法&#xff08;点击开发资源即可看到此页面&#xff09; 2,点击控制台-登录账号 …

13:HAL---SPI

目录 一:SPL通信 1:简历 2:硬件电路 3:移动数据图 4:SPI时序基本单元 A : 开/ 终条件 B:SPI时序基本单元 A:模式0 B:模式1 C:模式2 D:模式3 C:SPl时序 A:发送指令 B: 指定地址写 C:指定地址读 5&#xff1a;NSS(CS) 6&#xff1a;时钟 二: W25Q64 1:简历 2…

Star-CCM+通过将所有部件创建一个区域的方式分配至区域后子区域的分离,子区域材料属性的赋值,以及物理连续体的创建方法介绍

前言 上次介绍了将零部件分配至区域的方法与各个方法之间的区别&#xff0c;本文将继续上次的讲解&#xff0c;将其中的“将所有部件分配至一个区域”的应用进行补充。 如下图所示&#xff0c;按照将所有部件创建一个区域的方式分配至区域后&#xff0c;在区域下就会有一个区域…

springboot+vue实现登录注册,短信注册以及微信扫描登录

说明&#xff1a;微信扫描登录需要微信注册--要钱&#xff0c;感谢尚硅谷提供的免费接口&#xff1b;短信注册需要阿里云的注册很麻烦并且短信费&#xff0c;没有接口&#xff0c;所以不打算实现&#xff0c;不过能做出效果。 目录 一、建立数据库 二、后端idea实现接口 1.…