当前位置: 首页 > article >正文

java 中 List<T> 类型数据在 postgreSql 数据库中存储

一 属性添加注解

  1. 在类上面添加注解:

@TableName(autoResultMap = true)

  1. 在字段上面添加注解:

@TableField(value = "list", typeHandler = UserHandler.class) private List<User> list = new ArrayList<>();

二 创建 UserHandler 类

package com.demo.handler;

import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.demo.domain.pojo.User;
import org.apache.ibatis.type.MappedTypes;

import java.util.List;

@MappedTypes({List.class, User.class})
public class UserHandler extends AbstractJsonTypeHandler<List<User>> {

  @Override
  protected List<User> parse(String json) {
    return JsonUtils.fromString(json, List.class, User.class);
  }

  @Override
  protected String toJson(List<User> obj) {
    return JsonUtils.objectToString(obj);
  }
}

如果在使用改类时,只需将文件中的 User 替换为自己的类就行

概括下,这个解析器中的 parse 方法类似咱们的 set 方法,是将数据库中的 json 类型数据转为 List 类型数据;反之,toJson 是将 List 类型数据转为 json 数据格式,最后通过 mybatisplus 存储到数据库中. 具体实现可以看下面的 JsonUtils 工具类.

package com.demo.handler;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;


public class JsonUtils {
  private static final ObjectMapper objectMapper = new ObjectMapper();

  //初始化相关的配置
  static {
    //只引用不为空的值
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);

    //取消默认转换timestemp
    objectMapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);

    //忽略空bean转换错误
    objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

    //忽略在json中存在,在java对象不存在的错误
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    // 解决jackson2无法反序列化LocalDateTime的问题
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    objectMapper.registerModule(new JavaTimeModule());
  }

  /**
   * 将java对象转换成json字符串
   *
   * @param obj java 对象
   * @param <T>
   * @return
   */
  public static <T> String objectToString(T obj) {
    if (obj == null) {
      return null;
    }
    try {
      return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
    } catch (JsonProcessingException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 将json字符串转换成java对象
   *
   * @param json   字符串
   * @param tClass 要转换的对象
   * @param <T>
   * @return
   */
  public static <T> T getObjetFormString(String json, Class<T> tClass) {
    if (StringUtils.isBlank(json) || tClass == null) {
      return null;
    }

    try {
      return tClass.equals(String.class) ? (T) json : objectMapper.readValue(json, tClass);
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 将字符串转换成java对象
   *
   * @param json           字符串
   * @param tTypeReference 对象
   * @param <T>
   * @return
   */
  public static <T> T fromString(String json, TypeReference<T> tTypeReference) {
    if (StringUtils.isBlank(json) || tTypeReference == null) {
      return null;
    }

    try {
      return tTypeReference.getType().equals(String.class) ? (T) json : objectMapper.readValue(json, tTypeReference);
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 将json字符串转换成java集合对象
   *
   * @param json            字符串
   * @param collectionClass 集合类型
   * @param elementClazzes  成员类型
   * @param <T>
   * @return
   */
  public static <T> T fromString(String json, Class<?> collectionClass, Class<?>... elementClazzes) {
    JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClazzes);
    try {
      return objectMapper.readValue(json, javaType);
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    }
  }
}

该文件是工具类,配合 UserHandler 类,无需任何改动,直接粘贴即可

三 数据库字段设置

这里只需要将对应的字段类型设置为 json 即可,这里就不贴图了.

还需要将数据库连接后面加上stringtype=unspecified,例如:

jdbc:postgresql://*.*.*.*:5432/demo?currentSchema=demo,SYS_CATALOG&stringtype=unspecified

否则报错:PSQLException: ERROR: column “list” is of type json but expression is of type varchar

额外说明一个事情,可以说是一个 bug,上述效果在 selectById 查询时是成功的,但是在查询返回体是 List 时,list 字段会返回空集合,问了下 ai,说是数据库为了简洁高效,会跳过解析器,断点测试也确实是这样,至于如何解决,我现在是循环单个查询,最后合并,实属无奈,如果有哪位兄弟能搞定,还麻烦大致说下原因.

文章仓促就之,是在已经已经实现的代码上直接说明,如有读者发现文章有不足或是无法实现效果,可以留言.

如果文章确实有效,还望读者点赞收藏,感谢~


http://www.kler.cn/a/372294.html

相关文章:

  • Linux菜鸟级常用的基本指令和基础知识
  • Python深度学习GRU、LSTM 、BiLSTM-CNN神经网络空气质量指数AQI时间序列预测及机器学习分析|数据分享...
  • Backend - C# 的日志 NLog日志
  • Uncaught ReferenceError: __VUE_HMR_RUNTIME__ is not defined
  • 基于单片机的家庭智能垃圾桶(论文+源码)
  • 个人健康信息系统|Java|SSM|VUE| 前后端分离
  • 有效沟通与系统思考
  • 数据结构和算法-动态规划(3)-经典问题
  • Springboot整合RocketMQ分布式事务
  • 博科交换机SNMP采集(光衰)信息
  • 【Hive复杂数据类型和函数】全网总结最全的Hive函数
  • Next.js、Prisma 和 MySQL 实践示例
  • js获取浏览器指纹
  • rabbitmq高级特性(1):消息确认,持久性,发送方确认和重试机制
  • 在软件工程开发中,瀑布式开发和螺旋式开发的优缺点比较
  • 【数据结构】树-二叉树-堆(上)
  • 堆Heap
  • 医院信息化与智能化系统(13)
  • React Query已过时?新一代请求工具横空出世
  • 日本也有九九乘法表?你会读吗?柯桥零基础学日语到蓝天广场
  • openharmony北向开发入门教程汇总
  • 【非关系型分布式数据库】HBase从入门到面试学习总结
  • Python实现随机分布式延迟PSO优化算法(RODDPSO)优化DBSCAN膨胀聚类模型项目实战
  • IDEA 安装热部署 JRebel -新版-亲测有效
  • Android13预置应用及授权开发
  • Thread类及线程的核心操作