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

一、前言

在 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";

    /**
     * 关键位置!!!
     */
    @Override
    public 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);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String sqlJson = rs.getString(columnName);
        if (StringUtils.isNotBlank(sqlJson)) {
            return sqlJson;
        }
        return null;
    }

    // 根据列索引,获取可以为空的结果
    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String sqlJson = rs.getString(columnIndex);
        if (StringUtils.isNotBlank(sqlJson)) {
            return sqlJson;
        }
        return null;
    }

    @Override
    public 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 mapper
    PUBLIC "-//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>

业务代码

    /**
     * 新增数据
     */
    @Override
    public 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;
    }


本文完结!

相关推荐

  1. springboot集成mybatis处理json类型

    2024-07-12 06:30:02       57 阅读
  2. MyBatis:PostGreSQL的jsonb类型处理器

    2024-07-12 06:30:02       24 阅读
  3. 浅谈一下关系型数据库中json类型字段的处理

    2024-07-12 06:30:02       22 阅读
  4. SpringMVC--处理json

    2024-07-12 06:30:02       44 阅读
  5. json字符串的处理

    2024-07-12 06:30:02       36 阅读
  6. Json高效处理方法

    2024-07-12 06:30:02       33 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 06:30:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 06:30:02       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 06:30:02       58 阅读
  4. Python语言-面向对象

    2024-07-12 06:30:02       69 阅读

热门阅读

  1. Xcode本地化全攻略:打造多语言应用的秘诀

    2024-07-12 06:30:02       25 阅读
  2. C++ const 关键字详解

    2024-07-12 06:30:02       27 阅读
  3. 东方博宜1627 - 暑期的旅游计划(2)

    2024-07-12 06:30:02       26 阅读
  4. 防火、防盗、防windows defender

    2024-07-12 06:30:02       27 阅读
  5. Linux 之前的 Unix 桌面沉浮启示录

    2024-07-12 06:30:02       29 阅读
  6. 从 Github 安装 R packages 不完全指南

    2024-07-12 06:30:02       23 阅读
  7. 【面试题】MySQL(第四篇)

    2024-07-12 06:30:02       26 阅读
  8. C++学习笔记

    2024-07-12 06:30:02       27 阅读
  9. Spring AOP 使用方式

    2024-07-12 06:30:02       29 阅读
  10. filex容错模块(掉电安全)

    2024-07-12 06:30:02       27 阅读
  11. HashMap源码解析

    2024-07-12 06:30:02       29 阅读
  12. 开发一个HTTP模块

    2024-07-12 06:30:02       22 阅读