Postman发送Get请求返回重复结果 Spring Boot JPA实体序列化异常
你遇到的问题核心是Jackson序列化双向关联时的无限递归,并非数据库查询返回了重复数据:Chemistry和ChemistryAnswer为双向一对一关联,序列化返回JSON时,Jackson会先序列化Chemistry的answer属性,接着序列化ChemistryAnswer的question属性,又回到Chemistry对象循环往复,最终呈现出大量重复嵌套的相同内容。
解决方案
以下三种方案按需选择即可:
方案1:使用关联注解打断循环(推荐)
这是双向关联序列化的标准解决方案,在关系的维护方加@JsonManagedReference,被维护方加@JsonBackReference:
修改Chemistry类的answer属性:
@OneToOne(mappedBy = "question",cascade = CascadeType.ALL) @JsonManagedReference private ChemistryAnswer answer = new ChemistryAnswer();
修改ChemistryAnswer类的question属性:
@OneToOne @JoinColumn(name = "question_id") @JsonBackReference private Chemistry question;
序列化时只会返回Chemistry下的answer内容,不会返回answer下的question字段,完美打断循环。
方案2:直接忽略循环字段
如果不需要在返回结果中展示answer关联的question信息,可以直接给ChemistryAnswer的question属性加@JsonIgnore注解:
@OneToOne @JoinColumn(name = "question_id") @JsonIgnore private Chemistry question;
这个方案实现最简单,适合不需要反向关联序列化的场景。
方案3:用对象唯一标识避免重复序列化
如果需要保留双向关联的序列化,可以给两个实体类都加@JsonIdentityInfo注解,Jackson会用对象ID代替重复出现的同一对象:
给Chemistry类加类注解:
@Entity @Table(name = "Chemistry") @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class Chemistry { // 原有代码不变 }
给ChemistryAnswer类加类注解:
@Entity @Table(name = "Chemistryanswer") @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class ChemistryAnswer { // 原有代码不变 }
这个方案序列化后如果同一对象重复出现,只会输出一次完整内容,后续只输出ID值,避免了无限递归同时保留了关联关系。
额外注意事项
- 你在
Chemistry类中直接初始化private ChemistryAnswer answer = new ChemistryAnswer(),如果查询到的Chemistry没有关联的answer记录,序列化时会返回空的ChemistryAnswer对象而不是null,如有需要可以去掉初始化逻辑。 - 你同时引入了
spring-boot-starter-data-rest和自定义RestController,注意不要出现路径冲突,目前配置的路径没有冲突无需修改。
内容的提问来源于stack exchange,提问作者Chinedu
相关产品推荐
相关产品推荐

