【Mybatis-Plus】【PostgreSQL】List<T> 类型数据如何存数据库

在这里插入图片描述

前言

实现基于postgresql,springboot,spring mvc和mybatis-plus。

核心原理是将List<T>转为JSONArray类型,数据库对应字段为json类型,即可完成存储。

实现

建表

建表SQL语句如下:

create table test.image_info (
   id serial PRIMARY key NOT null,
   image_address text    NOT NULL,
   image_owner text    NOT NULL,
   download_times int8  default 10,
   authorized_user json,
   is_deleted int8 NOT null
);

SQL 语句创建一个名为 image_info 的表,该表包含:

id
数据类型为 serial,这意味着它是一个自动递增的整数类型。
设置为主键(PRIMARY KEY),这意味着每一行的 id 值必须是唯一的,不能有重复。
设置为 NOT NULL,这意味着这一列的值不能为空。

image_address
数据类型为 text,这意味着它可以存储任意长度的文本字符串。
设置为 NOT NULL,这意味着这一列的值不能为空。

image_owner
数据类型为 text,这意味着它可以存储任意长度的文本字符串。
设置为 NOT NULL,这意味着这一列的值不能为空。

download_times
数据类型为 int8,这意味着它可以存储 8 字节的整数。
设置了默认值为 10(default 10),这意味着如果插入数据时没有为这一列提供值,那么它的值将默认为 10。

authorized_user
数据类型为 json,这意味着它可以存储 JSON 格式的字符串。
这一列可以用来存储有权访问该图片的用户信息,这些信息是以 JSON 格式存储的。

is_deleted
数据类型为 int8,这意味着它可以存储 8 字节的整数。
设置为 NOT NULL,这意味着这一列的值不能为空。
这一列通常用于标记该记录是否已被删除。例如,1 可以表示已删除,0 可以表示未删除。

通过这个 image_info 表,我们可以存储和管理图像的相关信息,如图像地址、所有者、下载次数、授权用户以及是否被删除等。

ArrayTypeHandler.java

创建List处理器,ArrayTypeHandler.java:

package org.sample.handler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.*;
import java.util.Arrays;
import java.util.List;

/**
 * 
 */
@MappedJdbcTypes(JdbcType.ARRAY)
@MappedTypes(Object.class)
public class ArrayTypeHandler extends BaseTypeHandler<Object> {

    private static final String TYPE_NAME_VARCHAR = "varchar";
    
    private static final String TYPE_NAME_INTEGER = "integer";
    
    private static final String TYPE_NAME_BOOLEAN = "boolean";
    
    private static final String TYPE_NAME_NUMERIC = "numeric";
    
    private static final String TYPE_NAME_LONG = "bigint";

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        Object[] arrayObject;
        if (parameter instanceof List) {
            arrayObject = ((List) parameter).toArray();
        } else {
            arrayObject = (Object[]) parameter;
        }
        Connection conn = ps.getConnection();

        if (arrayObject.length > 0) {
            String typeName = TYPE_NAME_VARCHAR;
            if (arrayObject[0] instanceof Integer) {
                typeName = TYPE_NAME_INTEGER;
            } else if (arrayObject[0] instanceof String) {
                typeName = TYPE_NAME_VARCHAR;
            } else if (arrayObject[0] instanceof Boolean) {
                typeName = TYPE_NAME_BOOLEAN;
            } else if (arrayObject[0] instanceof Double) {
                typeName = TYPE_NAME_NUMERIC;
            } else if (arrayObject[0] instanceof Long) {
                typeName = TYPE_NAME_LONG;
            }
            Array array = conn.createArrayOf(typeName, arrayObject);
            ps.setArray(i, array);
        } else {
            ps.setArray(i, null);
        }


    }

    @Override
    public List<Object> getNullableResult(ResultSet resultSet, String s) throws SQLException {
        return getArray(resultSet.getArray(s));
    }

    @Override
    public List<Object> getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return getArray(resultSet.getArray(i));
    }

    @Override
    public List<Object> getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return getArray(callableStatement.getArray(i));
    }

    private List<Object> getArray(Array array) {
        if (array == null) {
            return null;
        }
        try {
            return Arrays.asList((Object[]) array.getArray());
        } catch (Exception e) {
        }
        return null;
    }
}


自定义的 MyBatis 类型处理器 ArrayTypeHandler,它继承自 BaseTypeHandler。这个类型处理器主要用于处理 Java 数组或 List 与数据库中的数组类型(如 PostgreSQL 的 ARRAY 类型)之间的转换:

@MappedJdbcTypes(JdbcType.ARRAY):表示这个类型处理器用于处理 JdbcType.ARRAY 类型的数据。
@MappedTypes(Object.class):表示这个类型处理器可以处理 Object 类型的数据。

setNonNullParameter 方法:
这个方法在插入或更新数据时被调用,将 Java 数组或 List 转换为数据库中的 ARRAY 类型。首先判断传入的参数 parameter 是 List 还是数组,并将其转换为 Object[] 类型的 arrayObject。

根据 arrayObject[0] 的类型确定数据库中 ARRAY 类型的元素类型,并创建一个对应类型的 Array 对象。使用 PreparedStatement 的 setArray 方法将 Array 对象设置到 SQL 语句的相应位置。
getNullableResult 方法:
这些方法在查询数据时被调用,将数据库中的 ARRAY 类型转换为 Java 数组或 List。分别针对 ResultSetCallableStatement 提供了三个重载版本的 getNullableResult 方法。
所有这些方法都调用了私有方法 getArray,并将返回的数组转换为 List。
getArray 方法:这个私有方法负责从给定的 Array 对象中获取实际的数组数据。

如果 Array 对象为 null,则返回 null。否则,调用 Array.getArray 方法获取实际的数组,并将其转换为 List 返回。

ArrayTypeHandler 类主要用于在 MyBatis 中处理 Java 数组或 List 与数据库中的 ARRAY 类型之间的转换,使得 MyBatis 能够正确地将数组或 List 数据存入数据库以及从数据库中读取数组或 List 数据。

ImageInfo

我们有entity ImageInfo.java如下:

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@TableName(value = "test.image_info ")
public class ImageInfo implements Serializable {


    /**
     * ID
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @TableField(value = "image_address")
    private String imageAddress;

    @TableField(value = "image_owner")
    private String imageOwner;

    @TableField(value = "download_times")
    private int downloadTimes;

    @TableField(value = "authorized_user", typeHandler = ArrayTypeHandler.class)
    private JSON authorizedUser;

    @TableField(value = "is_deleted")
    private int isDeleted;

}

实现

核心实现过程:


		// 创建entity
		List<String> finalAuthorizedUsers = authorizedUsers;
        ImageInfo imageInfo = new ImageInfo();
        imageInfo.setId(0L);
        imageInfo.setImageOwner(username);
        imageInfo.setAllowDownloadTimes(imageDownloadTimes);
        imageInfo.setAuthorizedUser(finalAuthorizedUsers);
        imageInfo.setIsDeleted(IsDeletedEnum.NO.getCode());
        imageInfo.setCreateTime(new Timestamp(System.currentTimeMillis()));
        imageInfo.setCreateUser(username);
        imageInfo.setUpdateUser(username);

		// 插入数据库
        int insert = imageInfoServiceMapper.insert(imageInfo);
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锥栗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值