Postgres JSON字段保存报错:column类型为json但表达式为smallint[]
PostgreSQL JSON字段保存时类型不匹配问题排查与解决
问题场景
PostgreSQL数据库中category表有一个data_processing_steps JSON类型字段,实体类定义如下:
@Type(JsonType.class) @Column(columnDefinition = "json") private Set<DataProcessingStep> dataProcessingSteps = new HashSet<>();
对应的Flyway迁移脚本:
ALTER TABLE category ADD COLUMN IF NOT EXISTS data_processing_steps json not null default '[]'::json;
保存实体时抛出错误:
[ERROR: column "data_processing_steps" is of type json but expression is of type smallint[]
SQL日志显示参数被识别为数组类型:
DEBUG org.hibernate.SQL[135] - insert into category (active,label,created_by,created_date,data_processing_steps) values (?,?,?,?,?) 2024-07-08 22:11:01.087 [main] TRACE org.hibernate.orm.jdbc.bind[24] - binding parameter (1:BOOLEAN) <- [true] 2024-07-08 22:11:01.087 [main] TRACE org.hibernate.orm.jdbc.bind[24] - binding parameter (2:VARCHAR) <- [label1] 2024-07-08 22:11:01.087 [main] TRACE org.hibernate.orm.jdbc.bind[24] - binding parameter (3:VARCHAR) <- [user@domain.com] 2024-07-08 22:11:01.087 [main] TRACE org.hibernate.orm.jdbc.bind[24] - binding parameter (4:TIMESTAMP_UTC) <- [2024-07-08T22:11:01.087618+03:00] 2024-07-08 22:11:01.088 [main] TRACE org.hibernate.orm.jdbc.bind[24] - binding parameter (5:ARRAY) <- [[]]
错误原因
Hibernate默认会把Set类型集合映射为PostgreSQL的SQL数组类型(此处表现为smallint[]),但数据库字段定义为json类型,两者类型不匹配,导致插入操作时抛出类型错误。从日志可见,Hibernate将dataProcessingSteps参数识别为ARRAY而非JSON。
解决方法
1. 正确配置Hibernate Types注解(适用于Hibernate 5.x)
若使用com.vladmihalcea:hibernate-types库处理JSON类型,需确保注解配置完整,同时引入对应版本的依赖:
实体类配置:
import com.vladmihalcea.hibernate.type.json.JsonType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import org.hibernate.annotations.Type; @Entity public class Category { // 其他字段省略 @Type(JsonType.class) @Column(columnDefinition = "json NOT NULL DEFAULT '[]'::json") private Set<DataProcessingStep> dataProcessingSteps = new HashSet<>(); // getter、setter方法 }
Maven依赖示例(根据Hibernate版本选择对应artifactId):
<dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-55</artifactId> <version>2.20.0</version> </dependency>
2. 使用Hibernate 6+原生JSON映射
Hibernate 6及以上版本无需额外依赖,可直接用@JdbcTypeCode指定JSON类型:
import jakarta.persistence.Column; import jakarta.persistence.Entity; import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.type.SqlTypes; @Entity public class Category { // 其他字段省略 @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "json NOT NULL DEFAULT '[]'::json") private Set<DataProcessingStep> dataProcessingSteps = new HashSet<>(); // getter、setter方法 }
3. 验证数据库字段定义一致性
检查Flyway迁移脚本执行结果,确认category表的data_processing_steps字段确实为json类型,未被误修改为数组类型。
内容的提问来源于stack exchange,提问作者Lesha Pipiev
相关产品推荐
相关产品推荐

