SpringBoot3.1.2+Hibernate6迁移后:无法将[B转换为java.util.UUID
解决SpringBoot 3.1.2(Hibernate 6)迁移后PostgreSQL bytea转UUID的类型转换错误
问题核心
数据库中SAMPLE_ID列类型为bytea(二进制存储UUID),Java实体映射为java.util.UUID,Hibernate 6对UUID映射逻辑的变更导致查询时出现Cannot cast [B to java.util.UUID错误。
为什么之前的方案无效?
- 配置项错误:你使用了
hibernate.type.preferred_duration_jdbc_type=BINARY,这是针对Duration类型的配置,和UUID无关; - 转换器类型不匹配:自定义的
UuidConverter是将UUID转String,但数据库存储的是二进制bytea,类型不兼容; - 错误的JDBC类型注解:
UUIDJdbcType.class对应数据库原生uuid类型,而非bytea类型,无法处理二进制UUID的转换。
有效解决方案
方案1:修正Hibernate配置+指定正确的JDBC类型
- 添加正确的Hibernate配置:
spring.jpa.properties.hibernate.type.preferred_uuid_jdbc_type=BINARY
- 调整实体类注解,使用适配bytea的
BinaryUuidJdbcType,并修正columnDefinition为实际的bytea:
@Id @JdbcType(BinaryUuidJdbcType.class) @Column(name = "SAMPLE_ID", unique = true, nullable = false, columnDefinition = "bytea") @Getter @Setter private UUID id;
方案2:自定义适配bytea的UUID转换器
如果方案1不生效,可使用自定义转换器直接处理byte[]和UUID的互转:
@Converter(autoApply = true) public class UuidToByteaConverter implements AttributeConverter<UUID, byte[]> { @Override public byte[] convertToDatabaseColumn(UUID uuid) { if (uuid == null) { return null; } ByteBuffer buffer = ByteBuffer.wrap(new byte[16]); buffer.putLong(uuid.getMostSignificantBits()); buffer.putLong(uuid.getLeastSignificantBits()); return buffer.array(); } @Override public UUID convertToEntityAttribute(byte[] bytes) { if (bytes == null || bytes.length != 16) { return null; } ByteBuffer buffer = ByteBuffer.wrap(bytes); long mostSigBits = buffer.getLong(); long leastSigBits = buffer.getLong(); return new UUID(mostSigBits, leastSigBits); } }
实体类无需额外注解(因autoApply=true),若需指定单个属性使用,可在@Column上添加@Convert(converter = UuidToByteaConverter.class)。
关键说明
- Hibernate 6对UUID的映射做了严格区分:针对数据库原生
uuid类型用UUIDJdbcType,针对二进制存储(bytea)用BinaryUuidJdbcType; - 确保实体类的
columnDefinition与数据库实际列类型一致,避免Hibernate误判类型。
内容的提问来源于stack exchange,提问作者ram4sof
相关产品推荐
相关产品推荐

