Technologieaustausch

[PostgreSQL] Spring Boot Mybatis-plus PostgreSQL verarbeitet JSON-Typ-Situationen

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

I. Einleitung

Bei der Springboot-Projektentwicklung wird im Allgemeinen eine relationale Datenbank als Hauptdatenbank zum Speichern von Daten verwendet. Manchmal erfordern Geschäftsszenarien die Erweiterung benutzerdefinierter Geschäftsinformationen auf der vorhandenen Tabellenstruktur. In diesem Szenario wird im Allgemeinen Speicher vom Typ JSON verwendet. Dieser Artikel fasst die praktische Lösung für den Betrieb von JSON im Springboot-Projekt mithilfe von Mybatis-plus zusammen.

2. Technologie-Stack

Spring Boot + Mybatis-plus + PostgreSQL, ein bestimmtes Feld in der PostgreSQL-Datenbank ist vom JSON-Typ.

Fügen Sie hier eine Bildbeschreibung ein

3. Hintergrundanalyse

In MyBatis übernimmt der Typhandler (TypeHandler) die Rolle einer Brücke zwischen JavaType und JdbcType. Sie werden verwendet, um den Wert eines Java-Objekts beim Ausführen einer SQL-Anweisung auf ein PreparedStatement zu setzen oder um einen Wert aus einem ResultSet oder CallableStatement abzurufen.

MyBatis-Plus bietet Ihnen einige integrierte Prozessoren, die sein können TableField Anmerkungen werden schnell in den MyBatis-Container eingefügt, was den Entwicklungsprozess vereinfacht. Offizielles Referenzdokument für den Feldtypprozessor MyBatis-Plus:Feldtypprozessor |. MyBatis-Plus (baomidou.com)

JSON-Feldtyp-Handler

MyBatis-Plus verfügt über eine Vielzahl integrierter JSON-Prozessoren, darunter AbstractJsonTypeHandler und seine UnterkategorienFastjson2TypeHandlerFastjsonTypeHandlerGsonTypeHandlerJacksonTypeHandler Warten. Diese Prozessoren können JSON-Strings in und aus Java-Objekten konvertieren.

4. Programmanalyse

4.1 Speichern Sie JSON-Objekte direkt in der PostgreSQL-Datenbank

Die PostgreSQL-Datenbankfelder sind in der Abbildung oben dargestellt: param_config ist ein Feld vom Typ JSON.

Schritt 1: DO-Entitäten schreiben

Der Felddatentyp ist 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

Schritt 2: XML-Konfiguration entsprechender Schreibmethode

<!-- 关键代码!!!!!!! -->
<!-- 单个字段的类型处理器配置 -->
<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Sehen Sie sich die in der Datenbank gespeicherten Ergebnisse an, wie unten gezeigt:

Fügen Sie hier eine Bildbeschreibung ein

4.2 Speichern von JSON-Strings in der PostgreSQL-Datenbank

Fügen Sie zuerst nach der PostgreSQL-Datenbank-URL hinzu &stringtype=nicht angegebenBeachten Sie, dass Sie dies tun müssen, wenn dieser Konfiguration direkt der Datenbankname vorangestellt ist & Ersetzen mit?

Schritt 1: Schreiben der DO-Entitätsklasse

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

Schritt 2: XML-Konfiguration entsprechender Schreibmethode

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

Sehen Sie sich die in der Datenbank gespeicherten Ergebnisse an, wie unten gezeigt:

Fügen Sie hier eine Bildbeschreibung ein

5. Benutzerdefinierter Prozessortyp

In MyBatis-Plus können Entwickler zusätzlich zur Verwendung des integrierten Typprozessors auch Typprozessoren nach Bedarf anpassen.

Wenn Sie beispielsweise eine PostgreSQL-Datenbank verwenden, können Sie auf Felder vom Typ JSON stoßen. In diesem Fall können Sie einen benutzerdefinierten Typprozessor zur Verarbeitung von JSON-Daten erstellen.

5.1 Typhandler definieren

Das Folgende ist ein Beispiel für einen benutzerdefinierten JSON-Typ-Prozessor:

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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

5.2 Benutzerdefinierte Typprozessoren verwenden

Übergeben Sie in der Entitätsklasse TableField Anmerkungen geben benutzerdefinierte Typhandler an:

/**
 * 测试对象
 *
 * @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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

Mapper-Datei ändern

<?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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Geschäftscode

    /**
     * 新增数据
     */
    @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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

Dieser Artikel ist fertig!