Spring Boot下Hibernate给byte[]加@Lob注解报Bad value for type long错误
报错根因
这个问题本质是Hibernate对PostgreSQL的@Lob注解默认映射逻辑和你的实际表结构不匹配:
- PostgreSQL的二进制存储分为两类:
bytea类型:二进制内容直接存在业务表的对应列中,属于行内存储- 大对象(LOB):二进制内容统一存在系统表
pg_largeobject中,业务表的对应列仅存储该大对象的OID(long类型的唯一标识符)
- 当你给
byte[] content属性加上@Lob注解后,Hibernate默认会将该属性映射为PostgreSQL的大对象类型,读取时会尝试从content列取long类型的OID,再去系统表查实际二进制内容。但你的表中content列是bytea类型,直接存储的是二进制值\x4545...,Hibernate尝试把二进制值强制转换为long类型的OID,就触发了该报错,并非映射到了错误列。
为什么移除@Lob后运行正常
移除@Lob注解后,Hibernate会自动将byte[]类型的属性映射为PostgreSQL的bytea类型,和你建表时的列类型完全匹配,读写逻辑自然不会出错。
实现byte[]属性懒加载的正确方案
你不需要加@Lob注解也可以实现content属性的懒加载,只要满足两个前提即可:
- 开启Hibernate字节码增强:基础属性的懒加载依赖字节码增强能力,Spring Boot环境可以直接在配置文件中添加如下配置:
如果是Maven项目还需要额外配置spring.jpa.properties.hibernate.enhancer.enableLazyInitialization = truehibernate-enhance-maven-plugin插件开启懒加载增强。 - 保留
content属性上的@Basic(fetch = FetchType.LAZY)注解即可。
补充说明
这个情况不属于Hibernate的Bug,是对PostgreSQL二进制存储机制和Hibernate映射规则的误解导致的。如果确实要使用@Lob注解,需要将表中content列的类型从bytea改为oid,但这种方案需要额外处理大对象的生命周期清理,反而不如bytea方案易用。
内容的提问来源于stack exchange,提问作者Herioz
相关产品推荐
相关产品推荐

