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

news2024/11/18 12:02:21

项目架构

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,继承自 BaseEntity
    user_id VARCHAR(255) NOT NULL, -- 用户ID
    roles 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);
//        }
//    }
    @Override
    public 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);
        }
    }


    @Override
    public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return parseJsonToList(json);
    }

    @Override
    public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String json = rs.getString(columnIndex);
        return parseJsonToList(json);
    }

    @Override
    public 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();
        }
    }


}

保存数据

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2178839.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Junit和枚举ENUM

断言机制&#xff0c;JAVA中的断言机制是一种用于检查程序中某个条件是否为真的机制。它可以在程序运行时检查某个条件是否满足&#xff0c;如果不满足则会抛出AssertionError异常。 在java中,断言机制默认是关闭的。所以会输出u。 断言机制只是为了用来吃调试程序的&#xff0…

【设计模式-中介者模式】

定义 中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为设计模式&#xff0c;通过引入一个中介者对象&#xff0c;来降低多个对象之间的直接交互&#xff0c;从而减少它们之间的耦合度。中介者充当不同对象之间的协调者&#xff0c;使得对象之间的通信变得简单且…

fiddler抓包13_响应后断点 - 篡改响应

课程大纲 原理 响应后断点&#xff08;After Response Breakpoint&#xff09;&#xff1a;Fiddler拦截、篡改服务器返回的响应&#xff0c;再返回给客户端。 应用场景 1.分析服务器响应数据 2.测试前端对特定返回的处理、展示 3.模拟网络中断、不稳定场景 单个断点 VS 全局…

信息安全数学基础(22)素数模的同余式

前言 信息安全数学基础中的素数模的同余式是数论中的一个重要概念&#xff0c;它涉及到了素数、模运算以及同余关系等多个方面。 一、基本概念 素数&#xff1a;素数是指只能被1和它本身整除的大于1的自然数。素数在密码学中有着广泛的应用&#xff0c;如RSA加密算法就依赖于大…

2024年企业博客SEO趋势与策略

随着互联网的快速发展和搜索引擎算法的不断演进&#xff0c;企业博客作为内容营销和SEO&#xff08;搜索引擎优化&#xff09;的重要载体&#xff0c;正面临着前所未有的机遇与挑战。进入2024年&#xff0c;企业若想通过博客在激烈的市场竞争中脱颖而出&#xff0c;就必须紧跟S…

verilog实现FIR滤波系数生成(阶数,FIR滤波器类型及窗函数可调)

在以往采用 FPGA 实现的 FIR 滤波功能&#xff0c;滤波器系数是通过 matlab 计算生成&#xff0c;然后作为固定参数导入到 verilog 程序中&#xff0c;这尽管简单&#xff0c;但灵活性不足。在某些需求下&#xff08;例如捕获任意给定台站信号&#xff09;需要随时修改滤波器的…

产品管理- 互联网产品(5):运营知识与技能

了解运营 1、运营的基础是产品认清受众&#xff0c;切实解决问题、用户需求 2、运营活动贯穿产品的整个生命周期 3、找准用户&#xff0c;建立MVP 4、明确产品的应用场景。用户在何场景下基于何种需求使用产品&#xff1f;务必短流程 5、AARRR模型 6、运营管理流程类似产品管理…

【CAM350】使用总结 <一>{ 光绘Gerber 对齐 }

〇、废话&#xff1a; 由于allegro和CAM350之间参数设置的问题&#xff1b;导致钻孔层和数据交付生产出现数据问题&#xff0c;或者同一个工程前后迭代&#xff0c;需要找出差别。 一、打开CAM350,打开两份光绘文件 二、增加工艺边后&#xff0c;不是很方便的找出区别&#x…

水波荡漾效果+渲染顺序+简单UI绘制

创建场景及布置 创建新场景Main,在Main场景中创建一个plane物体&#xff0c;命名为WaterWavePla,具体数值及层级面板排布如下&#xff1a; 编写脚本 创建一个文件夹&#xff0c;用于存放脚本&#xff0c;命名Scripts,创建一个子文件夹Effect,存放特效相关脚本&#xff0c;创建…

[Linux]:线程(二)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;Linux学习 贝蒂的主页&#xff1a;Betty’s blog 与Windows环境不同&#xff0c;我们在linux环境下需要通过指令进行各操作&…

LQR算法核心思想

本章以倒立摆为解决目的 什么是线性二次型控制器&#xff08;LQR&#xff09; 开环系统 即状态变量的倒数 系统的状态空间矩阵A * 系统状态变量x A状态矩阵&#xff1a;描述系统本身物理特性的一个矩阵&#xff0c;它是由系统本身的机械结构、物理结构决定的&#xff0c;无法…

基于单片机8路数字电压表电压采集系统

**单片机设计介绍&#xff0c;基于单片机8路数字电压表电压采集系统 文章目录 前言概要功能设计设计思路 软件设计效果图 程序设计程序文章目录 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技…

【C#】BotSharp:开源机器学习平台

随着人工智能&#xff08;AI&#xff09;和自然语言处理&#xff08;NLP&#xff09;技术的迅速发展&#xff0c;聊天机器人已经成为现代应用和服务的重要组成部分。无论是智能客服、虚拟助手&#xff0c;还是业务自动化和数据分析&#xff0c;智能对话系统正在各个领域发挥重要…

【2024.9.29练习】R 格式

题目描述 题目分析 带小数点的高精度乘法。小数点在计算时忽略&#xff0c;只需在最终打印字符串的时候在合适位置四舍五入即可。对于&#xff0c;可理解为对d乘2总共n次。因此使用“单精度高精度”类型的算法足矣。 我的代码 一开始代码有错误&#xff0c;我只想到了对小数点…

GAMES101(作业8)

作业8 题目&#xff1a; 模拟绳子动画&#xff0c;包括基于物理的&#xff0c;和非物理的&#xff0c;应该修改的函数是:rope.cpp 中的void Rope::simulateEuler(... Rope::rope(...)&#xff0c;&#xff0c;void Rope::simulateVerlet(...) 代码框架&#xff1a; main:负…

9.26-9.29学习

一.项目结构的建立 5个微服务模块 新建好各个模块后&#xff0c;在项目pom下引入各模块。各pom文件指定springboot版本2.1.8.RELEASE .gitignore #表示任意路径下的xx文件 **/mvnw **/mvnw.cmd**/.mvn **/target/.idea**/.gitignore 二.数据库初始化 一个微服务模块对应一个数…

微信小程序 蓝牙通讯

客户的需求如下&#xff1a;通过微信小程序控制蓝牙ble设备(电子面膜)&#xff0c;通过不同指令控制面膜的亮度和时间。 01.首先看下客户的ble设备服务文档&#xff1a;(本部分需要有点蓝牙基础,在调试过程中可以用安卓软件nRF Connect软件来执行测试命令) 0xFFF1灯控命令 命…

PCL 法线空间采样

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 法线计算 2.1.2 基于法线进行采样 2.1.3 可视化原始点云和采样后的点云 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实…

英伟达的AI一键生成数字人物理运动动画框架:统一控制模式,提升交互性和沉浸感

在虚拟现实(VR)、增强现实(AR)和3D内容创作领域,创建具有真实感和动态性的虚拟角色一直是技术上的挑战。最近,英伟达推出了一种新的框架,通过将物理驱动的角色控制视为运动修复问题,实现了跨场景的虚拟角色控制。这一创新方法不仅支持多种控制模式,还能够生成连贯且自…