0

我有 2 个相互关联的实体。这两个实体应该以多对多关系相互映射,但是,我还需要它们各自关系的时间戳(当它发生时),所以我试图使用中间表来映射它们。

最初,这种关系是一对多的,但我意识到我实际上需要多对多,因为业务逻辑需要这样。结构还是一样的,因为有父子关系,但是这一次,一个孩子也应该有多个父母。

我的 BaseEntity 是一个抽象类,其中包含所有其他实体中存在的字段:

@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 个实体,它们应该以多对多样式关联。这是我的第一个实体,应该是父实体:

@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<>();
}

我的第二个实体被认为是子实体:

@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 个由多对多关系映射的实体;
  • 使用中间实体和一对多 + 多对一关联实现多对多;
  • 显示我的 UserEntity 时获得递归;

更新:我设法使用我对这个问题的回答中描述的不同方法来解决这个问题。

4

1 回答 1

0

我通过实现复合键结构并仅使用@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 类(角色的定义):

@Nullable
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user", orphanRemoval = true)
private List<UserRole> roleList = new ArrayList<>();

RoleEntity 类(用户的定义)

@Nullable
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "role", orphanRemoval = true)
private List<UserRole> userList = new ArrayList<>();

这似乎有效,不再返回无限 JSON 递归。

于 2021-06-08T14:01:22.730 回答