JPA实体关联中@JsonBackReference导致Location不返回如何解决
问题根源
关联字段不返回是@JsonBackReference和@JsonManagedReference的使用方向错误导致的。
两个注解的固定序列化规则:
- 标注
@JsonManagedReference的字段会正常参与序列化输出 - 标注
@JsonBackReference的字段会在序列化时被直接忽略,作用是阻断双向关联的无限递归
当前代码中,Users类的location字段被标记为@JsonBackReference,所以序列化User时该字段会被直接过滤,不会出现在返回结果中。
另外所有关联属性配置了FetchType.LAZY懒加载,若JPA会话在查询结束后立即关闭,即使注解配置正确,也会因为无法加载关联数据抛出异常或返回空。
修复方案
方案1:调整注解配对方向
按照引用关系修正注解标记位置:
- Users与Location的关联:Location是被引用方,Users持有Location的外键,因此将Users类
location字段的注解改为@JsonManagedReference,Location类users集合字段的注解改为@JsonBackReference - Users与Posts的关联:当前注解配置正确(Users类
posts字段为@JsonManagedReference,Posts类users字段为@JsonBackReference),无需修改
修正后的核心代码片段:
// Users类location字段 @JsonManagedReference @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "location_id",insertable =false, updatable =false) private Location location;
// Location类users字段 @JsonBackReference @OneToMany(mappedBy = "location", cascade = CascadeType.ALL) private List<Users> users;
同时处理懒加载问题,在查询User时使用JOIN FETCH一次性加载关联的Location和Posts数据,避免会话关闭后无法读取关联属性,Repository层查询示例:
@Query("select u from Users u left join fetch u.location left join fetch u.posts where u.id = :id") Optional<Users> getbyId(Integer id);
方案2:使用@JsonIgnoreProperties替代配对注解(更推荐)
@JsonManagedReference/@JsonBackReference的缺陷是固定会忽略反向引用的字段,灵活度低。可以直接删除这两个注解,改用@JsonIgnoreProperties阻断递归,既不会触发无限循环,也不会丢失需要返回的字段。
修改后的实体类核心配置:
// Location类users字段 @JsonIgnoreProperties("location") @OneToMany(mappedBy = "location", cascade = CascadeType.ALL) private List<Users> users;
// Users类配置 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "location_id",insertable =false, updatable =false) private Location location; @JsonIgnoreProperties("users") @OneToMany(mappedBy = "users", cascade = CascadeType.ALL) private List<Posts> posts;
// Posts类users字段 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "users_id",insertable =false, updatable =false) private Users users;
这种配置下,序列化任意实体时,所有关联属性都会正常输出,只有检测到循环引用时才会忽略指定的反向字段,不会出现字段丢失问题。
内容的提问来源于stack exchange,提问作者SpicySandwich
相关产品推荐
相关产品推荐

