首页 > 解决方案 > Spring Data Rest - 无法使用 PUT 或 PATCH 更新嵌套对象

问题描述

我在 Attribute 和 AttributeGroup 之间有多对多的关系。AttributeGroup 包含许多属性,这些属性可以是多个 AttributeGroup 的子级。虽然 Attribute 是 AttributeGroup 的子关系,但它始终是在自己的存储库中创建的,即,希望在 AttributeGroup 之前创建 Attribute,并且在创建 AttributeGroup 期间添加子关系时。使用属性 repo,我可以执行所有 CRUD 操作,并使用 attributeGroup repo,成功处理 CRUD 操作。在 AttributeGroup 创建期间,与 Attribute 的关系也按预期工作。接下来,如果我想更改关系,即删除现有属性和/或添加另一个属性,它不起作用。我读到更新嵌套对象 PATCH 有效,但 PATCH 抛出异常

java.lang.IllegalArgumentException: Can not set java.lang.Long field Attribute.id to AttributeGroup

请让我知道这个实现有什么问题。

属性组.java

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.List;

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class AttributeGroup implements Serializable {
    private static final long serialVersionUID = -8264102706248686536L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;

    String name;
    String displayName;

    @NotNull
    @Size(min = 1)
    @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.REFRESH})
    List<Attribute> attributes;
}

属性.java

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Attribute implements Serializable {
    private static final long serialVersionUID = 8806808817130076030L;

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

    String name;

    String value;

    AttributeType attributeType;

    ArrayList<String> values;

    @ManyToMany(mappedBy = "attributes")
    @ToString.Exclude
    List<AttributeGroup> attributeGroups;
}

属性类型.java

public enum AttributeType {
    TEXT("Text Only");

    private final String attributeType;

    AttributeType(String productType) {
        this.attributeType = productType;
    }
}

标签: spring-data-jpamany-to-manyspring-data-rest

解决方案


bidirectinoal关系中,您需要同步关系的双方才能删除实体。

AttributeGroup是关系的所有者。所以,它必须有一个像下面这样的方法:

public void removeAttribute(Attribute attribute){
    if(attributes.contains(attribute)){
        attributes.remove(attribute);
        attribute.getAttributeGroups().remove(this);
    }
}

此外,在Attribute课堂上你应该有:

@PreRemove
void removeAttributeFromAttributeGroups(){
        for (AttributeGroup attributeGroup : attributesGroups) {
            attributeGroup.removeAttribute(this);
        }
}

相同的程序适用于Add操作。


推荐阅读