使用@JsonManagedReference与@JsonBackReference出现无限递归问题
问题解决方案
问题根源
- 实体层
@JsonManagedReference、@JsonBackReference注解使用位置颠倒,且parentDocument字段同时加了@JsonIgnore导致注解逻辑冲突 - ModelMapper映射时将实体的完整自关联关系同步到了DTO、Response层,子文档对象保留了
parentDocument父引用,序列化时触发父子对象循环嵌套 - Service层存在空指针隐患:未判断查询返回的
storedDocumentEntity是否为null,直接调用其get方法会在查询无结果时报空指针
修复方案
方案1:拆分响应结构(最推荐,符合业务规则)
你的业务规则明确要求子文档不可关联下级,因此直接拆分响应类,子文档返回结构不包含任何关联字段,从根源切断循环可能:
// 父文档响应类 public class DocumentResponse { private Long id; private String documentId; private String fileName; // 子文档用无关联的简化结构 private List<ChildDocumentResp> documents; } // 子文档简化响应类,无任何关联属性 public class ChildDocumentResp { private Long id; private String documentId; private String fileName; }
调整ModelMapper映射逻辑,将子文档集合直接映射为ChildDocumentResp类型即可。
方案2:用Jackson注解切断循环
如果不需要拆分响应类,直接在Response类的关联字段上加注解即可:
方式2.1:忽略父引用字段
给Response类的parentDocument字段加@JsonIgnore,序列化时自动忽略父引用,不会触发循环:
public class DocumentResponse { private Long id; private String documentId; private String fileName; @JsonIgnore // 序列化时忽略父引用,避免循环 private DocumentResponse parentDocument; private Set<DocumentResponse> documents; }
方式2.2:用对象唯一标识去重序列化
给Response类加@JsonIdentityInfo注解,序列化时同一个id的对象只会完整输出一次,后续出现仅用id代替:
import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class DocumentResponse { // 原有属性保持不变 }
方案3:修复实体层注解(可选)
如果需要直接序列化实体(不推荐,推荐用DTO隔离),修正注解位置即可:
@Entity @Table(name = "documents") public class DocumentEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 父引用用@JsonBackReference,序列化时忽略 @JsonBackReference @ManyToOne(fetch = FetchType.LAZY) private DocumentEntity parentDocument; // 子集合用@JsonManagedReference,序列化时正常输出 @JsonManagedReference @OneToMany(mappedBy = "parentDocument", fetch = FetchType.LAZY) private Set<DocumentEntity> documents; @Column(nullable = false, unique = true) private String documentId; @Column(nullable = false) private String fileName; }
删除parentDocument字段上冗余的@JsonIgnore注解,避免和@JsonBackReference逻辑冲突。
额外BUG修复
修正Service层的判空逻辑,先判断查询结果是否为null:
DocumentEntity storedDocumentEntity = documentRepository.findByDocumentIdAndParentDocumentNull(documentId); // 先判实体是否为空 if(storedDocumentEntity == null) { throw new AppFileNotFoundException("Oops file not found"); } documentDtoResponse = modelMapper.map(storedDocumentEntity, DocumentDto.class);
内容的提问来源于stack exchange,提问作者davidvera
相关产品推荐
相关产品推荐

