【PostgreSQL】Spring boot + Mybatis-plus + PostgreSQL 处理json类型情况

Spring boot + Mybatis-plus + PostgreSQL 处理json类型情况

  • 一、前言
  • 二、技术栈
  • 三、背景分析
  • 四、方案分析
    • 4.1 在PostgreSQL 数据库中直接存储 json 对象
    • 4.2 在PostgreSQL 数据库中存储 json 字符串
  • 五、自定义类型处理器
    • 5.1 定义类型处理器
    • 5.2 使用自定义类型处理器

一、前言

在 Springboot 项目开发中,一般使用关系型数据库作为主库存储数据,有时候业务场景需要在既有的表结构上,扩展自定义业务信息。这种场景下一般使用json类型存储。本文总结 Springboot 项目中,借助 Mybatis-plus 操作json实践方案。

二、技术栈

Spring boot + Mybatis-plus + PostgreSQL,在 PostgreSQL 数据库中某一个字段为 json 类型。

在这里插入图片描述

三、背景分析

在 MyBatis 中,类型处理器(TypeHandler)扮演着 JavaType 与 JdbcType 之间转换的桥梁角色。它们用于在执行 SQL 语句时,将 Java 对象的值设置到 PreparedStatement 中,或者从 ResultSet 或 CallableStatement 中取出值。

MyBatis-Plus 给大家提供了提供了一些内置的类型处理器,可以通过 TableField 注解快速注入到 MyBatis 容器中,从而简化开发过程。MyBatis-Plus 字段类型处理器官方参考文档:字段类型处理器 | MyBatis-Plus (baomidou.com)

JSON 字段类型处理器

MyBatis-Plus 内置了多种 JSON 类型处理器,包括 AbstractJsonTypeHandler 及其子类 Fastjson2TypeHandlerFastjsonTypeHandlerGsonTypeHandlerJacksonTypeHandler 等。这些处理器可以将 JSON 字符串与 Java 对象相互转换。

四、方案分析

4.1 在PostgreSQL 数据库中直接存储 json 对象

PostgreSQL 数据库字段如上图所示:param_config 是一个 json 类型的字段。

步骤一:DO实体写法

字段数据类型为 com.alibaba.fastjson2.JSONObject

@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {private Long id;.../*** 关键代码!!!* 必须开启映射注解** @TableName(autoResultMap = true)** 选择对应的 JSON 处理器,并确保存在对应的 JSON 解析依赖包*/@TableField(value = "param_config", typeHandler = JacksonTypeHandler.class)// 或者使用 FastjsonTypeHandler// @TableField(typeHandler = FastjsonTypeHandler.class)private JSONObject paramConfig;
}

步骤二:XML 配置对应写法

<!-- 关键代码!!!!!!! -->
<!-- 单个字段的类型处理器配置 -->
<result column="param_config" jdbcType="VARCHAR" property="paramConfig" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" /><!-- 多个字段中某个字段的类型处理器配置 -->
<resultMap id="departmentResultMap" type="com.baomidou...DepartmentVO"><result property="director" column="director" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" />
</resultMap>
<select id="selectPageVO" resultMap="departmentResultMap">select id,name,director from department ...
</select>

查看保存在数据库中的结果,如下图所示:

在这里插入图片描述

4.2 在PostgreSQL 数据库中存储 json 字符串

先在 PostgreSQL 的数据库 URL 后面加上 &stringtype=unspecified,注意,如果此配置前面直接是数据库名字,则需要将 & 换成 ?

步骤一:DO实体类写法

@TableField(value = "param_config", typeHandler = JacksonTypeHandler.class)
private String paramConfig;

步骤二:XML 配置对应写法

<!-- 单个字段的类型处理器配置 -->
<result column="param_config" jdbcType="VARCHAR" property="paramConfig" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" />

查看保存在数据库中的结果,如下图所示:

在这里插入图片描述

五、自定义类型处理器

在 MyBatis-Plus 中,除了使用内置的类型处理器外,开发者还可以根据需要自定义类型处理器。

例如,当使用 PostgreSQL 数据库时,可能会遇到 JSON 类型的字段,这时可以创建一个自定义的类型处理器来处理 JSON 数据。

5.1 定义类型处理器

以下是一个自定义的 JSON 类型处理器的示例:

package com.ruoyi.common.utils.pg;import com.ruoyi.common.utils.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.postgresql.util.PGobject;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** @ClassName: JsonTypeHandlerPg* @Description: json对象处理* @Author: hjm* @Date: 2024-07-11 10:34*/
@MappedTypes(String.class)
public class JsonTypeHandlerPg extends BaseTypeHandler<String> {/*** 引入PGSQL提供的工具类PGobject*/private static final PGobject JSON_OBJECT = new PGobject();public static final String JSON_TYPE = "json";/*** 关键位置!!!*/@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, String param, JdbcType jdbcType) throws SQLException {JSON_OBJECT.setType(JSON_TYPE);JSON_OBJECT.setValue(param);ps.setObject(i, JSON_OBJECT);}@Overridepublic String getNullableResult(ResultSet rs, String columnName) throws SQLException {String sqlJson = rs.getString(columnName);if (StringUtils.isNotBlank(sqlJson)) {return sqlJson;}return null;}// 根据列索引,获取可以为空的结果@Overridepublic String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String sqlJson = rs.getString(columnIndex);if (StringUtils.isNotBlank(sqlJson)) {return sqlJson;}return null;}@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {String sqlJson = cs.getString(columnIndex);if (StringUtils.isNotBlank(sqlJson)) {return sqlJson;}return null;}
}

5.2 使用自定义类型处理器

在实体类中,通过 TableField 注解指定自定义的类型处理器:

/*** 测试对象** @author hjm* @date 2024-07-11*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("data_test")
public class DataTest extends BaseEntity {private static final long serialVersionUID = 1L;/*** 主键*/@TableId(value = "id")private Long id;/*** 关键位置!!!*/@TableField(typeHandler = JsonTypeHandlerPg.class)private String jsonData;
}

修改mapper文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.dt.mapper.DataTestMapper"><resultMap type="com.ruoyi.dt.domain.DataTest" id="DataTestResult"><result property="id" column="id"/><!-- 关键位置!!! --><result property="jsonData" column="json_data" typeHandler="com.ruoyi.common.utils.pg.JsonTypeHandlerPg"/><result property="createBy" column="create_by"/><result property="createTime" column="create_time"/><result property="updateBy" column="update_by"/><result property="updateTime" column="update_time"/></resultMap></mapper>

业务代码

    /*** 新增数据*/@Overridepublic Boolean insertByAo(DataTestAo ao) {DataTest add = BeanUtil.toBean(ao, DataTest.class);// 关键位置!!!add.setJsonData(JSONUtil.toJsonStr(ao));validEntityBeforeSave(add);boolean flag = baseMapper.insert(add) > 0;if (flag) {ao.setId(add.getId());}return flag;}

本文完结!

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

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

相关文章

SpringCloud--Eureka集群

Eureka注册中心集群 为什么要集群 如果只有一个注册中心服务器&#xff0c;会存在单点故障&#xff0c;不可以高并发处理所以要集群。 如何集群 准备三个EurekaServer 相互注册&#xff0c;也就是说每个EurekaServer都需要向所有的EureakServer注册&#xff0c;包括自己 &a…

漏洞扫描器之XRAY的安装及破解

XRAY简介 xray 是一款功能强大的安全评估工具&#xff0c;由多名经验丰富的一线安全从业者呕心打造而成&#xff0c;主要特性有&#xff1a; 检测速度快&#xff1a;发包速度快 ; 漏洞检测算法高效。 支持范围广&#xff1a;大至 OWASP Top 10 通用漏洞检测&#xff0c;小至…

接口测试框架基于模板自动生成测试用例!

引言 在接口自动化测试中&#xff0c;生成高质量、易维护的测试用例是一个重要挑战。基于模板自动生成测试用例&#xff0c;可以有效减少手工编写测试用例的工作量&#xff0c;提高测试的效率和准确性。 自动生成测试用例的原理 为了实现测试用例数据和测试用例代码的解耦&a…

[激光原理与应用-109]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 12 - 焊接工艺之影响焊接效果的因素

目录 一、影响激光焊接效果的因素 1.1、光束特征 1.2、焊接特征 1.3、保护气体 二、材料对焊接的影响 2.1 材料特征 2.2 不同材料对激光的吸收率 &#xff08;一&#xff09;、不同金属材料对不同激光的吸收率 1. 金属材料对激光的普遍反应 2. 不同波长激光的吸收率差…

React Hooks学习笔记

一、usestate的使用方法-初始化state函数 import React, { useState } from "react"; function App() {const [count, setCount] useState(0);return (<div><p>点击{count}次</p><button onClick{() > setCount(count 1)}>点击</bu…

为何现在大屏的UI设计和前端开发项目已经多到咱们快忙不过来了?

**为何现在大屏的UI设计和前端开发项目已经多到咱们快忙不过来了&#xff1f;** **一、引言** 随着科技的进步和消费者需求的不断升级&#xff0c;大屏设备&#xff08;如智能电视、车载屏幕、拼接屏等&#xff09;在各行各业中的应用越来越广泛。这导致了大屏UI设计和前端开…

四步教你实现一个前端的动态实时时间(可自定义时间格式)

前言&#xff1a;我是在Vue中做的 1、将你的实时时间放在一个合适的位置 <div style"position: relative; padding-top: 0px; margin-top: -5px"><div style"position: absolute; left: auto; color: black; background-color: #7fd584; font-size: 3…

欧科云链研究院:坎昆升级后,Layer2变得更好了吗?

本文由欧科云链研究院OKG Research联合PANews出品&#xff1a;以数据为导向&#xff0c;洞察真实的链上世界。 作者&#xff5c;Jason Jiang, OKG Research 坎昆升级后&#xff0c;以太坊L2的交易费用降低明显且吞吐量有所提升&#xff0c;但整体生态并没有迎来想象中的繁荣景…

教你怎么不开DLSS3.0也能有效提高永劫无间帧数

永劫无间&#xff0c;一款国风的多人对战竞技游戏&#xff0c;游戏画面特别精美&#xff0c;在游戏中给玩家强烈的打击感&#xff0c;玩家在游玩过程中仿佛置身于游戏&#xff0c;而且此游戏非常受玩家欢迎。游戏中可以进行三人、双人、单人进行游玩&#xff0c;我们需要选择出…

Numpy常用的30个经典操作以及代码演示

目录 以下是具体的操作步骤和示例代码&#xff1a; 数组创建 数组操作 数组计算 统计分析 矩阵操作 这些操作涵盖了数组创建、数组操作、数组计算、统计分析和矩阵操作等多个方面. 以下是具体的操作步骤和示例代码&#xff1a; 首先导入Numpy import numpy as np数组…

sublime中无法找到Package Control或Install Package

在Crtl Shift P 中无法查找到Package Control或Install Package或调用产生报错。 可以尝试在 首选项 ---- > 设置中 检查配置文件"ignored_packages":紧跟的中括号中是否为空&#xff0c;如果不为空请删除其中内容。 如果不确定内容&#xff0c;可以用下面的…

【Linux】日志

日志是记录软件运行过程中发生的事件的一种手段&#xff0c;通常包含以下内容&#xff1a; 时间戳&#xff1a;记录日志条目创建的确切时间。这对于追踪事件发生的时间顺序至关重要。日志级别&#xff1a;表示日志信息的严重性或重要性&#xff0c;常见的级别包括 DEBUG、INFO…

【Linux】Linux背景历史

Linux背景历史 Linux背景Linux是什么&#xff1f;计算机的发展unix发展史Linux发展史开源Linux官网以及版本更替Linux企业应用现状 Linux环境的安装 Linux背景 Linux是什么&#xff1f; Linux(Linux Is Not UniX)&#xff0c;一般指GNU/Linux&#xff0c;是一种免费使用和自由…

Qt QChart 曲线图表操作

学习目标&#xff1a;QChart 曲线图表操作 学习内容 QT中的QChart类提供了一个功能强大的图表绘制框架,可以根据需求方便高效地绘制各种类型的图表,主要特点如下: 支持多种常见图表类型,如线图、条形图、饼图、散点图等各种类型。开发者只需要选择合适的图表类和数据即可绘制…

一键调仓/组合买卖?篮子交易功能,PTrade如何进行篮子交易?

篮子交易&#xff0c;也叫组合交易&#xff0c;是指同时完成一个股票或期货组合的交易。 “篮子交易”功能&#xff0c;通过模板一键导入一篮子股票&#xff0c;可对篮子中的股票进行剔除 或使用持仓替代操作&#xff0c;同时可设定报价方式、单笔超价、交易方式等。并实时显示…

android13 rom 开发总纲说明

1. 这里是文章总纲&#xff0c;可以在这里快速找到需要的文章。 2. 文章一般是基于标准的android13&#xff0c;有一些文章可能会涉及到具体平台&#xff0c;例如全志&#xff0c;瑞芯微等一些平台。 3.系统应用 3.1系统应用Launcher3桌面相关&#xff1a; 3.2系统应用设置S…

HNU-2024操作系统实验-Lab9-Shell

一、 实验目的 理解Shell程序的原理、底层逻辑和Shell依赖的数据结构等 在操作系统内核MiniEuler上实现一个可用的Shell程序 能够根据相关原理编写一条可用的Shell指令 二、 实验过程 首先从底层出发&#xff0c;实现Shell程序 1.在src/include目录下新建prt_shell.h头文…

ROS基础学习-ROS运行管理

ROS运行管理 目录 1. ROS运行管理简述2. ROS元功能包2.1 概念2.2 作用2.3 实现 3. ROS-launch文件3.1. ROS节点管理launch文件3.1.1 概念3.1.2 作用3.1.3 使用 3.2 launch文件标签 1. ROS运行管理简述 ROS是多进程(节点)的分布式框架&#xff0c;一个完整的ROS系统实现&#x…

最新 Kubernetes 集群部署 + Contranerd容器运行时 + flannel 网络插件(保姆级教程,最新 K8S 1.28.2 版本)

资源列表 操作系统配置主机名IP所需插件CentOS 7.92C4Gk8s-master192.168.60.143flannel-cni-plugin、flannel、coredns、etcd、kube-apiserver、kube-controller-manager、kube-proxy、 kube-scheduler 、containerd、pause 、crictlCentOS 7.92C4Gk8s-node01192.168.60.144f…

VScode代码对齐快捷键

解决复制过来代码对齐格式问题。 左对齐&#xff1a;Ctrl[ 右对齐&#xff1a;Ctrl]