Spring Boot+PostgreSQL问题:JSON递归错误与关联字段为空
解决方案
问题1:查询Medecin时Cabinet非ID字段为空
原因:@ManyToOne默认使用懒加载(FetchType.LAZY),JPA仅返回Cabinet的代理对象(仅包含ID),实际字段未从数据库加载,导致序列化后非ID字段为空。
解决方法(推荐使用EntityGraph或Fetch Join,避免EAGER带来的性能问题)
方式1:使用@EntityGraph在Repository中指定关联加载
在Medecin的Repository接口中,给查询方法添加@EntityGraph注解,明确加载关联的Cabinet:
public interface MedecinRepository extends JpaRepository<Medecin, Long> { @EntityGraph(attributePaths = {"cabinet"}) Medecin findById(Long id); // 批量查询时也可使用 @EntityGraph(attributePaths = {"cabinet"}) List<Medecin> findAll(); }
方式2:使用Fetch Join的JPQL查询
通过JPQL的join fetch语法强制加载关联对象:
public interface MedecinRepository extends JpaRepository<Medecin, Long> { @Query("SELECT m FROM Medecin m JOIN FETCH m.cabinet WHERE m.id = :id") Medecin findByIdWithCabinet(@Param("id") Long id); }
方式3:修改fetch类型为EAGER(不推荐,可能导致性能损耗)
直接修改@ManyToOne的fetch属性,但会导致每次查询Medecin都强制加载Cabinet,仅适合关联数据必用的场景:
@ManyToOne(fetch = FetchType.EAGER) private Cabinet cabinet;
问题2:查询Cabinet时出现无限递归(StackOverflowError)
原因:Cabinet包含Medecin列表,Medecin又引用Cabinet,Jackson序列化时会循环遍历两者的关联关系,导致栈溢出。
解决方法:使用Jackson的双向引用注解
通过@JsonManagedReference和@JsonBackReference标记双向关联的父子关系,告诉Jackson序列化时忽略反向引用:
修改Medecin类
@Entity @Data @NoArgsConstructor @AllArgsConstructor public class Medecin extends User { private int inp; private String specialite; @ManyToOne(fetch = FetchType.LAZY) @JsonBackReference // 标记为反向引用,序列化时忽略 private Cabinet cabinet; }
修改Cabinet类
@Entity(name = "Cabinet") @Data @NoArgsConstructor @AllArgsConstructor public class Cabinet { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) @Column(name = "cabinet_id") private Long id; private String denomination; private String adresse; private int telephone; private double longitude; private double latitude; @OneToMany(mappedBy = "cabinet", cascade = CascadeType.ALL) @JsonManagedReference // 标记为正向引用,正常序列化 private List<Medecin> medecins = new ArrayList<>(); }
其他可选方案
- 使用
@JsonIgnore:在其中一方的关联字段添加该注解,直接忽略该字段的序列化(但会丢失关联数据,仅适合不需要返回该字段的场景)。 - 使用
@JsonIdentityInfo:给实体类添加该注解,通过ID标识对象,避免重复序列化(适合复杂关联场景):@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @Entity public class Cabinet { ... } @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @Entity public class Medecin extends User { ... }
内容的提问来源于stack exchange,提问作者Anas Hafidi
相关产品推荐
相关产品推荐

