首页 > 解决方案 > 如何将@JsonManagedReference 和@JsonBackReference 用于与最佳实践的多对多关系?

问题描述

我将非常感谢您解释我的问题。

我有 2 个实体和 1 个桥表实体,

假设他们是团队、用户和团队用户。

团队实体:

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "TEAM_ID")
    private Integer id;

    @JsonManagedReference
    @OneToMany(mappedBy = "team", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<TeamUsers> team_users = new HashSet<>();

用户实体:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@JsonBackReference
@OneToMany(mappedBy = "user")
private Set<TeamUsers> team_users = new HashSet<>();

TeamUserEntity(桥表):@EmbeddedId private TeamUsersId id;

@ManyToOne
@MapsId("teamId")
@JoinColumn(name = "team_id")
@JsonBackReference
private Team team;

@ManyToOne
@MapsId("userId")
@JoinColumn(name = "user_id")
@JsonManagedReference
private User user;

@Column(name = "active")
private int active;

如您所见,我使用@JsonManagedReference 和@JsonBackReference 来告诉程序查询实体的方向并避免无限递归。

现在,如果我在Team CRUDrepository上运行 get repo.findAll() ,我将获得所有 Team 对象,在内容中我将获得所有桥表数据,它还包括用户详细信息。

但是假设有时如果我想以相反的方式查询数据,我想获取所有用户信息并且对象应该包含所有团队信息,看起来像注释@JsonManagedReference 和 @JsonBackReference阻止了结果。

在现实世界的开发中,我们应该如何管理这里?

标签: javaspring-boot

解决方案


@JsonManagedReference注解@JsonBackReference用于处理循环引用。它们可用于以双向方式创建 JSON 结构。@JsonManagedReference注解用于目标 POJO 的子引用,这意味着它是在序列化过程中包含的前向引用,而@JsonBackReference注解是在序列化过程中省略的反向引用,通常用于相应的子类中。

因此,用@JsonBackReference此处注释的属性,即Team中的TeamUsers,将不会被序列化。这就是为什么当你试图让所有用户都在Team里面时TeamUsers,它是行不通的。此外,如果这样做,它将违反它们用于递归访问映射的注释的目的。

如果您想以任何一种方式获取数据,您应该使用@JsonIgnoreProperties而不是这两个注释。如下更改您的实体类,您将获得所需的输出。

Team类中,@JsonIgnoreProperties("team")team_users字段上设置再次忽略team该字段内部的映射,以避免递归映射。Team将您的班级更改为:

public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "TEAM_ID")
    private Integer id;

    @OneToMany(mappedBy = "team", cascade = CascadeType.ALL, orphanRemoval = true)
    @JsonIgnoreProperties("team")
    private Set<TeamUsers> team_users = new HashSet<>();

}

同样,在User类中,@JsonIgnoreProperties("user")team_users字段上设置再次忽略user该字段内部的映射,避免递归映射。User将您的班级更改为:

public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    @JsonIgnoreProperties("user")
    private Set<TeamUsers> team_users = new HashSet<>();
}

最后,在TeamUsers类中,@JsonIgnoreProperties("team_users")同时设置teamanduser字段以再次忽略team_users这些字段内的映射,以避免递归映射。TeamUsers将您的班级更改为:

public class TeamUsers {

    @EmbeddedId
    private TeamUserId id;

    @ManyToOne
    @MapsId("teamId")
    @JoinColumn(name = "team_id")
    @JsonIgnoreProperties("team_users")
    private Team team;

    @ManyToOne
    @MapsId("userId")
    @JoinColumn(name = "user_id")
    @JsonIgnoreProperties("team_users")
    private User user;

    @Column(name = "active")
    private int active;
}

现在,您可以以任何一种方式获取数据,而无需递归映射。


推荐阅读