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

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,继承自 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.kler.cn/news/324703.html

相关文章:

  • 【数据治理-设计数据标准】
  • 数据库入门不再难:克服学习障碍的实用技巧与演示
  • 《北方牧业》是什么级别的期刊?是正规期刊吗?能评职称吗?
  • 甄选范文“论软件架构建模技术与应用”,软考高级论文,系统架构设计师论文
  • 工程设备包括哪些内容?
  • Vue和axios零基础学习
  • 基于nodejs+vue的宠物医院管理系统
  • C# 打开文件,打开文件夹对话框
  • FLUX.1 AI图像生成行业的新挑战者
  • 《深度学习》—— 卷积神经网络(CNN)的简单介绍和工作原理
  • 【Linux基础IO】Linux IO编程入门:揭秘动态库与静态库的秘密
  • 大数据新视界 --大数据大厂之Cassandra 分布式数据库在大数据中的应用与调优
  • ansible实用模块
  • CSS网格布局
  • 【JS】forEach中push为何不会陷入死循环,稀疏数组空元素为何不会被遍历
  • 基于微信开发助手企鹅音乐微信小程序的设计与实现(源码+文档+讲解)
  • 上交所服务器崩溃:金融交易背后的技术隐患暴露杭州BGP高防服务器43.228.71.X
  • 双十一有什么好物推荐?绝对不能错过的五款产品
  • NLP技术在营业选址中的实践与探索
  • 【YashanDB知识库】GBK库,生僻字插入nvarchar2字段后乱码问题
  • 高通平台(2)Camera 效果 Fast tuning
  • Qt 项目优化实践方向
  • LeetCode题练习与总结:为运算表达式设计优先级--241
  • Kafka 的重平衡问题详解及解决方案
  • 【Linux】 tcp | 解除服务器对tcp连接的限制 | 物联网项目配置
  • (十七)、Mac 安装k8s
  • Redis桌面工具:Tiny RDM
  • py-mmcif包解析蛋白质结构的装配信息
  • 【NodeJS】npm、yarn、pnpm当前项目设置国内镜像源
  • 别人做谷歌seo凭什么比你好?