You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级SpringBoot 3.1.5后Postgres JsonBinaryType无法正常使用

解决Spring Boot 3.1.5中Postgres JsonB列与org.json.simple.JSONObject的持久化问题

问题根源

Spring Boot 3.x适配Hibernate 6,彻底重构了类型系统,原Hibernate 5时代的@TypeDef注解以及第三方JsonBinaryType(通常来自com.vladmihalcea:hibernate-types系列库)不再兼容。直接使用@JdbcTypeCode(SqlTypes.JSON)时,Hibernate无法自动解析org.json.simple.JSONObject的类型映射——因为它不是Hibernate默认支持的JSON载体类型。

可行解决方案

方案1:替换为Hibernate原生支持的JSON类型(最简便)

放弃org.json.simple.JSONObject,改用Hibernate内置支持的类型,无需额外转换器即可直接适配JsonB列:

示例:使用Map<String, Any?>

import lombok.AllArgsConstructor
import lombok.Builder
import lombok.Data
import lombok.NoArgsConstructor
import org.hibernate.annotations.JdbcTypeCode
import org.hibernate.type.SqlTypes
import jakarta.persistence.*
import java.util.UUID

@Entity
@Table(name = "myTable")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
data class MyEntity(
    @Id
    @Column(unique = true, nullable = false, updatable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    val id: UUID,

    @JdbcTypeCode(SqlTypes.JSON)
    @Column(columnDefinition = "jsonb", nullable = true)
    val objConfig: Map<String, Any?>? = null
)

注意:添加columnDefinition = "jsonb"明确指定Postgres列类型为JsonB,避免默认创建为普通json类型。

示例:使用Jackson的JsonNode

如果需要更灵活的JSON节点操作(比如动态遍历、修改JSON结构),可以用Jackson的JsonNode:

import com.fasterxml.jackson.databind.JsonNode
import lombok.AllArgsConstructor
import lombok.Builder
import lombok.Data
import lombok.NoArgsConstructor
import org.hibernate.annotations.JdbcTypeCode
import org.hibernate.type.SqlTypes
import jakarta.persistence.*
import java.util.UUID

@Entity
@Table(name = "myTable")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
data class MyEntity(
    @Id
    @Column(unique = true, nullable = false, updatable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    val id: UUID,

    @JdbcTypeCode(SqlTypes.JSON)
    @Column(columnDefinition = "jsonb", nullable = true)
    val objConfig: JsonNode? = null
)

方案2:自定义AttributeConverter保留org.json.simple.JSONObject

如果业务必须保留org.json.simple.JSONObject,可以实现JPA的AttributeConverter手动处理序列化/反序列化逻辑:

  1. 实现转换器类:
import jakarta.persistence.AttributeConverter
import jakarta.persistence.Converter
import org.json.simple.JSONObject
import org.json.simple.parser.JSONParser
import org.json.simple.parser.ParseException

@Converter(autoApply = false)
class JSONObjectConverter : AttributeConverter<JSONObject?, String?> {
    private val parser = JSONParser()

    override fun convertToDatabaseColumn(jsonObject: JSONObject?): String? {
        return jsonObject?.toJSONString()
    }

    override fun convertToEntityAttribute(dbData: String?): JSONObject? {
        if (dbData.isNullOrEmpty()) return null
        return try {
            parser.parse(dbData) as JSONObject
        } catch (e: ParseException) {
            throw RuntimeException("解析JSON字符串失败", e)
        }
    }
}
  1. 在实体类中绑定转换器:
import lombok.AllArgsConstructor
import lombok.Builder
import lombok.Data
import lombok.NoArgsConstructor
import org.hibernate.annotations.JdbcTypeCode
import org.hibernate.type.SqlTypes
import jakarta.persistence.*
import java.util.UUID

@Entity
@Table(name = "myTable")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
data class MyEntity(
    @Id
    @Column(unique = true, nullable = false, updatable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    val id: UUID,

    @Convert(converter = JSONObjectConverter::class)
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(columnDefinition = "jsonb", nullable = true)
    val objConfig: JSONObject? = null
)

@JdbcTypeCode(SqlTypes.JSON)配合转换器,确保Hibernate将数据以JsonB格式写入Postgres。

关键注意事项

  • 确保Postgres驱动版本适配Spring Boot 3.x,推荐使用org.postgresql:postgresql 42.6.0及以上版本。
  • 移除旧版hibernate-types依赖,Hibernate 6自带的JSON支持已覆盖绝大多数场景,混用会引发类型冲突。

内容的提问来源于stack exchange,提问作者vishal kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:43:17