配置UUID为实体ID后findAll返回异常ID值的问题排查
问题原因及解决办法
问题原因
- UUID序列化逻辑错误:Spring Boot 3默认使用的Jackson库对
UUID类型的序列化出现异常,将UUID字符串的每个字符转换为对应ASCII码的十六进制值拼接,导致返回的ID完全失真(例如原字符5被转为35,-被转为2d)。 - 自关联循环引用引发序列化异常:实体类中的
templateHelper自关联ManyToOne字段未做序列化控制,Jackson在序列化时陷入循环引用,导致对象被重复序列化,出现ID重复、key值错误的情况。 - @GeneratedValue注解与手动插入ID冲突:实体ID标注了
@GeneratedValue(strategy = GenerationType.UUID),Hibernate会默认接管ID生成逻辑,当手动插入UUID到数据库后,Hibernate加载实体时无法正确映射数据库中的字符串UUID到JavaUUID对象,进一步加剧了序列化问题。
解决办法
1. 修正UUID序列化方式
有两种可行方案:
- 字段级注解配置:在
id字段上添加序列化/反序列化注解,强制Jackson将UUID转为字符串格式输出:@Id @Column(name = "id", length = 36, updatable = false, nullable = false) @JsonSerialize(using = ToStringSerializer.class) @JsonDeserialize(using = UUIDDeserializer.class) private UUID id; - 全局Jackson配置:在Spring Boot配置类中设置全局规则,让UUID始终序列化为字符串:
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); // 开启UUID序列化为字符串 mapper.configure(SerializationFeature.WRITE_UUID_AS_STRING, true); return mapper; } }
2. 处理自关联循环引用
在templateHelper字段上添加@JsonIgnore注解,阻止Jackson序列化该字段,避免循环引用问题:
@ManyToOne @JoinColumn(name = "id_template_mirror", referencedColumnName = "id", foreignKey = @ForeignKey(name = "reference_itself_template")) @JsonIgnore private AppEmailTemplate templateHelper;
如果需要返回该字段的部分数据,也可以使用@JsonManagedReference和@JsonBackReference组合,但自关联场景下@JsonIgnore更为直接。
3. 移除@GeneratedValue注解
由于ID是手动插入的,不需要Hibernate自动生成,直接移除@GeneratedValue(strategy = GenerationType.UUID)注解,确保Hibernate完全从数据库读取ID值:
@Id @Column(name = "id", length = 36, updatable = false, nullable = false) private UUID id;
若后续需要同时支持手动插入和自动生成ID,可以自定义ID生成器,或者在数据插入时判断ID是否为空再决定是否生成。
内容的提问来源于stack exchange,提问作者Cristian Jacob Jimenez
相关产品推荐
相关产品推荐

