
本文讲解如何通过 Jackson 的 @JsonManagedReference 和 @JsonBackReference 注解解决父子实体双向关联导致的 JSON 序列化问题,确保查询 Loan 时能一并返回其关联的 User 信息,避免无限递归或字段丢失。
本文讲解如何通过 jackson 的 `@jsonmanagedreference` 和 `@jsonbackreference` 注解解决父子实体双向关联导致的 json 序列化问题,确保查询 loan 时能一并返回其关联的 user 信息,避免无限递归或字段丢失。
在 Spring Boot 中处理 JPA 实体间的一对多(User ↔ Loan)双向关联时,若直接序列化,极易触发 Jackson 的循环引用异常(如 StackOverflowError)或因 @JsonIgnore 过度使用而导致父级数据(如 User)完全不返回。您当前代码中调用 ele.getUser() 并试图手动赋值,但因 @JsonIgnore 存在于 Loan.user 字段,该属性始终被忽略,故前端仅收到空的 user 对象或 null。
根本解决方案是用 Jackson 提供的双向引用注解替代 @JsonIgnore,精准控制序列化方向:
✅ 正确做法:
- 在 父实体(User)的集合字段上使用 @JsonManagedReference(正向引用,会被序列化);
- 在 子实体(Loan)的关联字段上使用 @JsonBackReference(反向引用,不参与序列化,仅用于破环循环)。
修改后的实体定义如下:
// User.java(父实体)
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long mobile;
private String name;
private String email;
@ToString.Exclude
@OneToMany(cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
@JsonManagedReference // ✅ 允许序列化此集合(User → Loans)
private List<Loan> loans = new ArrayList<>();
}// Loan.java(子实体)
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
public class Loan {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String status;
@ToString.Exclude
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
@JsonBackReference // ✅ 不序列化此字段(Loan → User),避免循环
private User user;
}⚠️ 关键注意事项:
- @JsonBackReference 字段不会出现在最终 JSON 中,因此 Loan 对象本身不包含 user 数据 —— 这是设计使然。真正返回 user 信息的是 @JsonManagedReference 所在的 User.loans 集合,即:响应结构以 User 为根,其 loans 数组内嵌 Loan 对象。
- 若业务要求以 Loan 列表为根(如分页查询 Page<Loan>),且每个 Loan 需携带 User 基础信息(如 name, email),则应改用 DTO 投影 或 @EntityGraph + FetchType.EAGER(谨慎!),而非依赖双向序列化。例如:
// 推荐:定义 LoanWithUserDto
public record LoanWithUserDto(
Long loanId,
String status,
String userName,
String userEmail
) {}
// 在 Repository 中使用 JPQL 或 Projection 查询- 确保 fetch = FetchType.LAZY 与实际查询匹配:若未启用 @EnableSpringHttpSession 或未配置 spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true(不推荐生产使用),懒加载可能抛出 LazyInitializationException。此时建议在 Service 层显式调用 Hibernate.initialize(loan.getUser()),或改用 FetchType.EAGER(仅限低频、小数据量场景)。
总结:@JsonManagedReference / @JsonBackReference 是处理 JPA 双向关系 JSON 序列化的标准方案,它不改变数据加载逻辑,只规范输出结构。若需灵活控制每个 Loan 携带的 User 字段,请优先采用 DTO 模式,兼顾性能、可维护性与 API 清晰性。


















