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


}

保存数据

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

您好!对于使用Spring BootPostgreSQL存储和操作JSON格式数据的问题,您可以按照以下步骤进行操作: 1. 首先,在您的Spring Boot项目中添加PostgreSQL的依赖。您可以在Maven或Gradle配置文件中添加以下依赖项: ```xml <!-- Maven --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>版本号</version> </dependency> ``` ```groovy // Gradle implementation 'org.postgresql:postgresql:版本号' ``` 2. 确保您已经在PostgreSQL数据库中创建了一个表,该表包含一个JSON类型的列用于存储JSON数据。您可以使用以下DDL语句创建一个表: ```sql CREATE TABLE your_table ( id SERIAL PRIMARY KEY, json_data JSON ); ``` 3. 在您的Spring Boot应用程序中,您可以使用JPA(Java Persistence API)或Spring Data JDBC来访问和操作数据库。 - 如果您选择使用JPA,您需要创建一个实体类来映射到数据库表。在实体类中,您可以使用`@Column(columnDefinition = "json")`注解来指定该字段应该使用JSON数据类型。例如: ```java @Entity @Table(name = "your_table") public class YourEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(columnDefinition = "json") private String jsonData; // Getters and setters } ``` - 如果您选择使用Spring Data JDBC,您可以创建一个简单的POJO类,其中包含一个与数据库表列对应的字段。例如: ```java public class YourEntity { private Long id; private String jsonData; // Getters and setters } ``` 4. 在您的应用程序中,您可以使用JPA的Repository接口或Spring Data JDBC的Repository接口来执行数据库操作。例如,使用JPA的Repository接口: ```java public interface YourRepository extends JpaRepository<YourEntity, Long> { } ``` 5. 现在,您可以在您的业务逻辑中使用Repository接口来存储和检索JSON数据。例如,使用JPA的Repository接口: ```java @Service public class YourService { private final YourRepository yourRepository; public YourService(YourRepository yourRepository) { this.yourRepository = yourRepository; } public void saveJsonData(String jsonData) { YourEntity entity = new YourEntity(); entity.setJsonData(jsonData); yourRepository.save(entity); } public List<YourEntity> getAllEntities() { return yourRepository.findAll(); } } ``` 这样,您就可以使用Spring BootPostgreSQL存储和操作JSON格式数据了。希望对您有所帮助!如有任何疑问,请随时向我提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值