使用 Set 而不是 List 导致 "Could not write JSON: Infinite recursion" 异常

Using Set instead of List cause "Could not write JSON: Infinite recursion" exception

我在尝试访问端点 http://localhost:8080/categoryOfPermissions. I've researched and found various solutions here (@JsonManagedReference / @JsonBackReference, @JsonIgnore, @JsonIdentityInfo), but none of them seemed to work. Finally, I found an 时收到错误 “无法写入 JSON:无限递归”,说明必须从 Set 更改为 List,以便 @JsonIdentityInfo 解决方案起作用。我测试了它,从 Set 更改为 List 后它真的开始工作了。

我觉得很奇怪,但我发现了更奇怪的事情:从 Set 更改为 List 后,我​​删除了 @JsonIdentityInfo 注释,一切都继续工作。换句话说,我真正需要做的就是从 Set 更改为 List 以消除异常。没有其他的。不需要任何解决方案:@JsonManagedReference / @JsonBackReference@JsonIgnore@JsonIdentityInfo.

下面是产生异常的代码。我所要做的就是将 private Set<Permission> permission 更改为 private List<Permission> permission.

我想知道为什么,特别是因为我更喜欢使用 Set,以避免 Hibernate 使用“Bags”范式(这可能会导致 some undesirable behaviors)。

Permission.java :

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

    @NotBlank
    private String name;
            
    @NotNull    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "category_of_permission_id")
    private CategoryOfPermission categoryOfPermission;    
}

类别Permission.java :

@Entity
@Data
public class CategoryOfPermission{

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

    @NotBlank
    private String name;
            
    @NotNull    
    @OneToMany(mappedBy = "categoryOfPermission", fetch=FetchType.LAZY)
    private Set<Permission> permission;
}

CategoryOfPermissionRepo.java :

public interface CategoryOfPermissionRepo extends CrudRepository<CategoryOfPermission, Integer>{
}

是因为Java中的Set使用了equals契约来判断两个对象是否相同,而[=16=中的方法equals =] class 实现(使用 lombok)导致无限递归。

它是 Permission

equals 方法的生成代码的一部分
    Object this$categoryOfPermission = this.getCategoryOfPermission();
    Object other$categoryOfPermission = other.getCategoryOfPermission();
    if (this$categoryOfPermission == null) {
      if (other$categoryOfPermission != null) {
        return false;
      }
    } else if (!this$categoryOfPermission.equals(other$categoryOfPermission)) {
      return false;
    }

它是 CategoryOfPermission class

的生成代码
public boolean equals(final Object o) {
    if (o == this) {
      return true;
    } else if (!(o instanceof CategoryOfPermission)) {
      return false;
    } else {
      CategoryOfPermission other = (CategoryOfPermission)o;
      if (!other.canEqual(this)) {
        return false;
      } else {
        Object this$id = this.getId();
        Object other$id = other.getId();
        if (this$id == null) {
          if (other$id != null) {
            return false;
          }
        } else if (!this$id.equals(other$id)) {
          return false;
        }

        Object this$permission = this.getPermission();
        Object other$permission = other.getPermission();
        if (this$permission == null) {
          if (other$permission != null) {
            return false;
          }
        } else if (!this$permission.equals(other$permission)) {
          return false;
        }

        return true;
      }
    }
  }

如你所见 Permission class 调用 CategoryOfPermissionequals 方法 class 和 CategoryOfPermission 调用 equals 的方法Permision class 这最终导致了 Whosebug 问题!