中间人 Table 映射的多对多关系中的无限 JSON
Infinite JSON in ManyToMany relationship mapped by Intermediary Table
我有 2 个相互关联的实体。这两个实体应该以 Many-To-Many 关系相互映射,但是,我还需要有它们各自关系的时间戳(发生时),所以我试图使用中介 table.
最初,关系是 One-To-Many,但我意识到我实际上需要一个 Many-To-Many,因为业务逻辑需要这个。结构仍然是一样的,因为有一个 Parent-Child 关系,但是这次,一个 child 也应该有多个 parent。
我的 BaseEntity 是一个抽象 class,它包含存在于所有其他实体中的字段:
@Data
@MappedSuperclass
public abstract class BaseEntity {
@Id
@Min(100)
@Max(Integer.MAX_VALUE)
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
@CreationTimestamp
@Column(name = "Created_At", updatable = false)
protected ZonedDateTime createdDate;
@UpdateTimestamp
@Column(name = "Updated_At")
protected ZonedDateTime updatedDate;
@NotNull
@Column(name = "Is_Active")
protected Boolean active = true;
}
然后我的 2 个实体应该以 Many-To-Many 样式关联。这是我的第一个实体,应该是 parent:
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "User")
@EqualsAndHashCode(callSuper = true)
@TypeDefs( {
@TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class UserEntity extends BaseEntity {
@NotBlank
@Column(name = "User_Name", columnDefinition = "varchar(255) default 'N/A'")
private String userName;
@Nullable
@JoinColumn(name = "User_Id")
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<UserRole> roleList = new ArrayList<>();
}
我的第二个实体被认为是 child 实体:
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Role")
@Where(clause = "is_active = true")
@EqualsAndHashCode(callSuper = true)
public class RoleEntity extends BaseEntity {
@NotBlank
@Column(name = "Name")
private String name;
@JsonIgnore
@JoinColumn(name = "Role_Id")
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<UserRole> userList = new ArrayList<>();
}
我还有我的中介实体:
@Data
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Where(clause = "is_active = true")
@EqualsAndHashCode(callSuper = true)
@Table(name = "User_Role", uniqueConstraints= @UniqueConstraint(columnNames={"User_Id", "Role_Id"}))
public class UserRole extends BaseEntity {
// Adding @JsonIgnore here will only cause an error
@JoinColumn(name = "User_Id")
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false, targetEntity = UserEntity.class)
private UserEntity user;
@JoinColumn(name = "Role_Id")
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false, targetEntity = RoleEntity.class)
private RoleEntity role;
}
现在的问题是,当我尝试获取我的 UserEntity 时,我得到了无限递归。
到目前为止,我已经尝试使用@JsonIgnore、@JsonManagedReference、@JsonBackReference,但没有用,或者我根本不知道在哪里或如何正确使用它们。
回顾:
- 2 个实体由 Many-To-Many 关系映射;
- Many-To-Many 使用中间实体和 One-To-Many + Many-To-One 关联实现;
- 在显示我的 UserEntity 时获取递归;
更新:我设法使用我对这个问题的回答中描述的不同方法解决了这个问题。
我通过实现复合键结构并仅使用 @JsonIgnore 注释解决了这个问题:
@Getter
@Setter
@Embeddable
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class UserRoleKey implements Serializable {
@Column(name = "User_Id")
Long userId;
@Column(name = "Role_Id")
Long roleId;
}
这将在中间实体中使用,现在不再使用我的 BaseEntity。
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "User_Role", uniqueConstraints= @UniqueConstraint(columnNames={"User_Id", "Role_Id"}))
public class UserRole {
@JsonIgnore
@EmbeddedId
private UserRoleKey id;
@JsonIgnore
@MapsId("userId")
@JoinColumn(name = "User_Id")
@ManyToOne(optional = false, targetEntity = UserEntity.class)
private UserEntity user;
@MapsId("roleId")
@JoinColumn(name = "Role_Id")
@ManyToOne(optional = false, targetEntity = RoleEntity.class)
private RoleEntity role;
@CreationTimestamp
@Column(name = "Created_At", updatable = false)
private ZonedDateTime createdDate;
}
现在,对于我的两个实体,我有这样的定义:
UserEntity class(角色定义):
@Nullable
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user", orphanRemoval = true)
private List<UserRole> roleList = new ArrayList<>();
RoleEntity class(用户定义)
@Nullable
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "role", orphanRemoval = true)
private List<UserRole> userList = new ArrayList<>();
这似乎有效,不再是 returns 无限 JSON 递归。
我有 2 个相互关联的实体。这两个实体应该以 Many-To-Many 关系相互映射,但是,我还需要有它们各自关系的时间戳(发生时),所以我试图使用中介 table.
最初,关系是 One-To-Many,但我意识到我实际上需要一个 Many-To-Many,因为业务逻辑需要这个。结构仍然是一样的,因为有一个 Parent-Child 关系,但是这次,一个 child 也应该有多个 parent。
我的 BaseEntity 是一个抽象 class,它包含存在于所有其他实体中的字段:
@Data
@MappedSuperclass
public abstract class BaseEntity {
@Id
@Min(100)
@Max(Integer.MAX_VALUE)
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
@CreationTimestamp
@Column(name = "Created_At", updatable = false)
protected ZonedDateTime createdDate;
@UpdateTimestamp
@Column(name = "Updated_At")
protected ZonedDateTime updatedDate;
@NotNull
@Column(name = "Is_Active")
protected Boolean active = true;
}
然后我的 2 个实体应该以 Many-To-Many 样式关联。这是我的第一个实体,应该是 parent:
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "User")
@EqualsAndHashCode(callSuper = true)
@TypeDefs( {
@TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class UserEntity extends BaseEntity {
@NotBlank
@Column(name = "User_Name", columnDefinition = "varchar(255) default 'N/A'")
private String userName;
@Nullable
@JoinColumn(name = "User_Id")
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<UserRole> roleList = new ArrayList<>();
}
我的第二个实体被认为是 child 实体:
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Role")
@Where(clause = "is_active = true")
@EqualsAndHashCode(callSuper = true)
public class RoleEntity extends BaseEntity {
@NotBlank
@Column(name = "Name")
private String name;
@JsonIgnore
@JoinColumn(name = "Role_Id")
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<UserRole> userList = new ArrayList<>();
}
我还有我的中介实体:
@Data
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Where(clause = "is_active = true")
@EqualsAndHashCode(callSuper = true)
@Table(name = "User_Role", uniqueConstraints= @UniqueConstraint(columnNames={"User_Id", "Role_Id"}))
public class UserRole extends BaseEntity {
// Adding @JsonIgnore here will only cause an error
@JoinColumn(name = "User_Id")
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false, targetEntity = UserEntity.class)
private UserEntity user;
@JoinColumn(name = "Role_Id")
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false, targetEntity = RoleEntity.class)
private RoleEntity role;
}
现在的问题是,当我尝试获取我的 UserEntity 时,我得到了无限递归。
到目前为止,我已经尝试使用@JsonIgnore、@JsonManagedReference、@JsonBackReference,但没有用,或者我根本不知道在哪里或如何正确使用它们。
回顾:
- 2 个实体由 Many-To-Many 关系映射;
- Many-To-Many 使用中间实体和 One-To-Many + Many-To-One 关联实现;
- 在显示我的 UserEntity 时获取递归;
更新:我设法使用我对这个问题的回答中描述的不同方法解决了这个问题。
我通过实现复合键结构并仅使用 @JsonIgnore 注释解决了这个问题:
@Getter
@Setter
@Embeddable
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class UserRoleKey implements Serializable {
@Column(name = "User_Id")
Long userId;
@Column(name = "Role_Id")
Long roleId;
}
这将在中间实体中使用,现在不再使用我的 BaseEntity。
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "User_Role", uniqueConstraints= @UniqueConstraint(columnNames={"User_Id", "Role_Id"}))
public class UserRole {
@JsonIgnore
@EmbeddedId
private UserRoleKey id;
@JsonIgnore
@MapsId("userId")
@JoinColumn(name = "User_Id")
@ManyToOne(optional = false, targetEntity = UserEntity.class)
private UserEntity user;
@MapsId("roleId")
@JoinColumn(name = "Role_Id")
@ManyToOne(optional = false, targetEntity = RoleEntity.class)
private RoleEntity role;
@CreationTimestamp
@Column(name = "Created_At", updatable = false)
private ZonedDateTime createdDate;
}
现在,对于我的两个实体,我有这样的定义:
UserEntity class(角色定义):
@Nullable
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user", orphanRemoval = true)
private List<UserRole> roleList = new ArrayList<>();
RoleEntity class(用户定义)
@Nullable
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "role", orphanRemoval = true)
private List<UserRole> userList = new ArrayList<>();
这似乎有效,不再是 returns 无限 JSON 递归。