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

Springboot+PostgreSQL+MybatisPlus存储JSON或List、数组(Array)数据

项目架构

Springboot+PostgreSQL+MybatisPlus
从Mongodb转过来的项目,有存储json数据的需求,但是在mybatis-plus上会出点问题
报错: Error updating database. Cause: org.postgresql.util.PSQLException 字段 “” 的类型为 jsonb, 但表达式的类型为 character varying 建议:你需要重写或转换表达式

实体类定义:

@EqualsAndHashCode(callSuper = true)
@Data
@TableName("tb_user_role")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TbUserRole extends BaseEntity {@TableField("user_id")String userId;@JsonInclude(JsonInclude.Include.NON_EMPTY)List<String> roles; // 存储为 JSONB@JsonInclude(JsonInclude.Include.NON_EMPTY)List<String> permissions; // 存储为 JSONB
}

SQL

CREATE TABLE tb_user_role (id VARCHAR(255) PRIMARY KEY, -- 主键ID,继承自 BaseEntityuser_id VARCHAR(255) NOT NULL, -- 用户IDroles JSONB, -- 角色,存储为 JSONB 类型permissions JSONB, -- 权限,存储为 JSONB 类型deleted BOOLEAN DEFAULT FALSE, -- 逻辑删除标识create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间
);

前端传入的结构

     @Schema(description = "角色,传入的对象需要从Role接口获取")List<String> roles;@Schema(description = "权限,传入的对象需要从Permission接口获取")List<String> permissions;

存储时的问题

Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1c1e6475]
2024-09-27 17:48:43.398 ERROR [tid] [sid] [pid] [nio-8050-exec-1] c.s.w.h.GlobalExceptionHandler@viewExceptionHandler:66 : 
### Error updating database.  Cause: org.postgresql.util.PSQLException: 错误: 字段 "roles" 的类型为 jsonb, 但表达式的类型为 character varying建议:你需要重写或转换表达式位置:117
### The error may exist in com/sgcchg/data/mapper/UserRoleMapper.java (best guess)
### The error may involve com.sgcchg.data.mapper.UserRoleMapper.insert-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO tb_user_role  ( id, user_id, roles, permissions, deleted, create_time, update_time )  VALUES (  ?, ?, ?, ?, ?, ?, ?  )
### Cause: org.postgresql.util.PSQLException: 错误: 字段 "roles" 的类型为 jsonb, 但表达式的类型为 character varying建议:你需要重写或转换表达式位置:117
; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: 错误: 字段 "roles" 的类型为 jsonb, 但表达式的类型为 character varying建议:你需要重写或转换表达式位置:117 location: com.sgcchg.business.impl.user.UserServiceImpl:101

问题解决

修改Entity定义

@EqualsAndHashCode(callSuper = true)
@Data
@TableName("tb_user_role")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TbUserRole extends BaseEntity {@TableField("user_id")String userId;@TableField(typeHandler = ListToStringTypeHandler.class)@JsonInclude(JsonInclude.Include.NON_EMPTY)List<String> roles; // 存储为 JSONB@TableField(typeHandler = ListToStringTypeHandler.class)@JsonInclude(JsonInclude.Include.NON_EMPTY)List<String> permissions; // 存储为 JSONB
}

添加TypeHandler

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;public class ListToStringTypeHandler extends BaseTypeHandler<List<String>> {private static final ObjectMapper objectMapper = new ObjectMapper();//    @Override
//    public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
//        // 将 List 转为 JSON 字符串存储
//        try {
//            ps.setString(i, objectMapper.writeValueAsString(parameter));
//        } catch (JsonProcessingException e) {
//            throw new SQLException("Could not convert list to JSON", e);
//        }
//    }@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {try {String jsonString = objectMapper.writeValueAsString(parameter);ps.setObject(i, jsonString, JdbcType.OTHER.TYPE_CODE); // 使用 JDBC 的 OTHER 类型插入 JSONB} catch (JsonProcessingException e) {throw new SQLException("Could not convert list to JSON", e);}}@Overridepublic List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {String json = rs.getString(columnName);return parseJsonToList(json);}@Overridepublic List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String json = rs.getString(columnIndex);return parseJsonToList(json);}@Overridepublic List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {String json = cs.getString(columnIndex);return parseJsonToList(json);}private List<String> parseJsonToList(String json) {if (json == null || json.trim().isEmpty()) {return Collections.emptyList();}try {return objectMapper.readValue(json, List.class);} catch (JsonProcessingException e) {return Collections.emptyList();}}}

保存数据

之后即可保存数据
在数据库中可看到:
在这里插入图片描述

相关文章:

  • 机器学习(2):机器学习的相关术语
  • .Net 6.0 监听Windows网络状态切换
  • [CSP-J 2022] 解密
  • LeetCode 热题 100 回顾8
  • 智能红外抄表系统的设计与实现(论文+源码)_kaic
  • iTextPDF中,要实现表格中的内容在数据长度超过边框时自动换行
  • 组合优化与凸优化 学习笔记5 对偶拉格朗日函数
  • 开放原子开源基金会网站上的开源项目Opns存在缓冲区溢出缺陷
  • 设计模式之模版方法模式
  • 【Linux系列】CMA (Contiguous Memory Allocator) 简单介绍
  • 【QT Quick】基础语法:基础类与控件
  • 【分页】Spring Boot 列表分页 + javaScript前台展示
  • 程序员如何提升并保持核心竞争力?——深入钻研、广泛学习与软技能的培养
  • Grafana链接iframe嵌入Web前端一直跳登录页面的问题记录
  • python自动更新chromedriver
  • 2017 年终总结 —— 在路上
  • k8s如何管理Pod
  • PHP 7 修改了什么呢 -- 2
  • vue自定义指令实现v-tap插件
  • 高性能JavaScript阅读简记(三)
  • 基于web的全景—— Pannellum小试
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 我的zsh配置, 2019最新方案
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 一天一个设计模式之JS实现——适配器模式
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • # AI产品经理的自我修养:既懂用户,更懂技术!
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #07【面试问题整理】嵌入式软件工程师
  • #pragma 指令
  • (pojstep1.1.2)2654(直叙式模拟)
  • (SERIES10)DM逻辑备份还原
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (五)MySQL的备份及恢复
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • (轉貼) UML中文FAQ (OO) (UML)
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .net core 连接数据库,通过数据库生成Modell
  • .NET 材料检测系统崩溃分析
  • .NET 回调、接口回调、 委托
  • @JsonSerialize注解的使用
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)
  • [240812] X-CMD 发布 v0.4.5:更新 gtb、cd、chat、hashdir 模块功能
  • [AIGC] 解题神器:Python中常用的高级数据结构
  • [AIGC] 如何建立和优化你的工作流?
  • [Android开源]EasySharedPreferences:优雅的进行SharedPreferences数据存储操作
  • [Arduino学习] ESP8266读取DHT11数字温湿度传感器数据
  • [bzoj2957]楼房重建
  • [C/C++]关于C++11中的std::move和std::forward
  • [C++] Windows中字符串函数的种类