在 PostgreSQL 中使用 JSONB 类型并结合 MyBatis-Plus 实现自动注入,主要有以下几种方案:

方案一

User对象

@Data
@TableName(value = "t_user", autoResultMap = true)
public class User {

    @TableId(type = IdType.AUTO)
    private Long id;

    //jsonb
    @TableField(value = "dept", typeHandler = JsonbTypeHandler.class)
    private Dept dept;

}

JsonbTypeHandler

import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.postgresql.util.PGobject;

import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;


@MappedTypes({Object.class})
public class JsonbTypeHandler extends JacksonTypeHandler {

    public JsonbTypeHandler(Class<?> type) {
        super(type);
        getObjectMapper().registerModule(new JavaTimeModule());
        getObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        if (ps != null) {
            PGobject jsonObject = new PGobject();
            jsonObject.setType("jsonb");
            jsonObject.setValue(toJson(parameter));
            ps.setObject(i, jsonObject);
        }
    }
}

自定义SQL查询

public interface UserMapper extends BaseMapper<User> {

    @Select("""
            SELECT * FROM t_user WHERE id = #{id}
            """)
    @Results({
            @Result(column = "dept", property = "dept",
                    typeHandler = JsonbTypeHandler.class)
    })
    EmcDidCamera getById(String id);

}

其他方案

1. 创建 JSONB TypeHandler

@MappedTypes({Map.class, List.class, Object.class})
@MappedJdbcTypes(JdbcType.OTHER)
public class JsonbTypeHandler extends BaseTypeHandler<Object> {
    
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, 
                                    Object parameter, JdbcType jdbcType) 
                                    throws SQLException {
        try {
            String json = objectMapper.writeValueAsString(parameter);
            ps.setObject(i, json, Types.OTHER);
        } catch (JsonProcessingException e) {
            throw new SQLException("JSON转换失败", e);
        }
    }
    
    @Override
    public Object getNullableResult(ResultSet rs, String columnName) 
                                    throws SQLException {
        String json = rs.getString(columnName);
        return parseJson(json);
    }
    
    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) 
                                    throws SQLException {
        String json = rs.getString(columnIndex);
        return parseJson(json);
    }
    
    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) 
                                    throws SQLException {
        String json = cs.getString(columnIndex);
        return parseJson(json);
    }
    
    private Object parseJson(String json) throws SQLException {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        try {
            return objectMapper.readValue(json, Object.class);
        } catch (Exception e) {
            throw new SQLException("JSON解析失败: " + json, e);
        }
    }
}

2. 实体类配置

@Data
@TableName(value = "your_table", autoResultMap = true)
public class YourEntity {
    
    @TableId(type = IdType.AUTO)
    private Long id;
    
    private String name;
    
    // 方式1:使用泛型
    @TableField(typeHandler = JsonbTypeHandler.class)
    private Map<String, Object> attributes;
    
    // 方式2:指定具体类型
    @TableField(typeHandler = JsonbTypeHandler.class)
    private List<String> tags;
    
    // 方式3:自定义对象
    @TableField(typeHandler = JsonbTypeHandler.class)
    private Config config;


    @TableField(typeHandler = JsonbTypeHandler.class)
    private List<Config> configs;

	public void setConfigs(List configs) {

		if(CollUtil.isEmpty(configs)){
			return;
		}

		Object first = configs.getFirst();
		if(first instanceof Map){
			this.configs= JSONUtil.toList(JSONUtil.toJsonStr(configs), Config.class);
		}
	}



}



Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐