升级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手动处理序列化/反序列化逻辑:
- 实现转换器类:
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) } } }
- 在实体类中绑定转换器:
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:postgresql42.6.0及以上版本。 - 移除旧版
hibernate-types依赖,Hibernate 6自带的JSON支持已覆盖绝大多数场景,混用会引发类型冲突。
内容的提问来源于stack exchange,提问作者vishal kumar
相关产品推荐
相关产品推荐

