【问题标题】:Spring Data Rest - PUT is not working for associated reference types?Spring Data Rest - PUT 不适用于关联的引用类型?
【发布时间】:2017-10-22 08:39:32
【问题描述】:

我为 Spring Data Rest 项目实现了以下域类。

@Entity
@Data
public class Address {

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

    private String houseName;

    private String apartmentNumber;

    @ManyToOne
    private City city;

    @ManyToOne
    private Country country; 

}

现在我通过发送带有以下 JSON 的 POST 创建地址资源。

{   
    "houseName":"Some House",
    "apartmentNumber":"13 B",
    "city": "http://localhost:8080/city/1"
    "country":"http://localhost:8080/countries/1"
}

当我使用以下 JSON 向端点 http://localhost:8080/addresses/1 发送 PUT 请求时,houseName 的值会更新。然而,即使我为城市发送不同的 URI,城市仍然保持不变。

{   
    "houseName":"Another House",
    "apartmentNumber":"13 B",
    "city": "http://localhost:8080/city/2"
    "country":"http://localhost:8080/countries/1"
}

如果我发送 PATCH 而不是 PUT,则城市值也会更新。那么我该如何解决呢?

更新 1

国家级

@Data
@Entity
public class Country {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long countryID;

    private String countryName;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "country", orphanRemoval = true)
    private List<City> cities;

}

城市等级

@Data
@Entity
public class City {

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

    private String cityName;

    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
}

【问题讨论】:

  • 您在“city”和“country”中传递字符串值,但您已将它们声明为用户定义的数据类型 City、Country..
  • 但它们是 URI,所以 spring data rest 会知道如何取消引用它们
  • 请同时分享国家和城市实体类。
  • @mephis-slayer 我已经用城市和国家类更新了问题

标签: spring rest spring-boot spring-data-rest spring-hateoas


【解决方案1】:

我遇到了同样的问题,并设法找到了一些相关信息。

这是Spring Data Rest 版本2.5.7 的更改,是“出于目的”。

Oliver Drotbohm 的回答是:

我对此进行了调查,但我认为您希望事情能够在 他们不工作的方式。 PUT 请求不考虑与 可链接资源,即指向的相关资源 链接。原因有两个:

  1. 如果我们考虑使用有效负载中关联字段的 URI 来更新这些关联,就会出现一个问题,即应该做什么 如果未指定 URI,则会发生。与当前行为,链接 关联根本不是有效负载的一部分,因为它们只驻留 在 _links 块中。在这种情况下,我们有两个选择:擦除 未提交的关联,这打破了“PUT what you GET” 方法。只有擦除使用 null 提供的那些才会排序 模糊“你把资源的整个状态”。
  2. 由于 1. 中提到的所有原因,公开了可以直接操作的专用关联资源。

因此,如果您想更改资源的两个状态,看起来像这样 加上联想的同时,我猜想暴露一个专门的 资源来做到这一点是要走的路。

您可以在 Jira Spring 网站上找到完整答案:Unable to update associated resource using PUT request on the item resource

(我写的堆栈溢出问题在这里:Spring Data Rest - PUT on repository silently fails on child references

【讨论】:

    【解决方案2】:

    如果您使用 Hibernate 作为您的 JPA 提供程序,那么您必须让知道实体在两侧是如何映射的,并指出它是如何在子实体中映射的,这将在交易。

    已编辑和更新:

    //城市类

    @Entity
    public class City {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "city_id")
        private Long cityID;
    
        @Column(name = "city_name")
        private String cityName;
    
        @ManyToOne
        private Country country;
    
        @OneToMany(cascade = CascadeType.ALL, mappedBy = "city", orphanRemoval = true)
        private List<Address> addresses;
    }
    

    // 国家类

    @Entity
    public class Country {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "country_id")
        private Long countryID;
    
        @Column(name = "country_name")
        private String countryName;
    
        @OneToMany(cascade = CascadeType.ALL, mappedBy = "country", orphanRemoval = true)
        private List<City> cities = new ArrayList<>();;
    
        @OneToMany(cascade = CascadeType.ALL, mappedBy = "country", orphanRemoval = true)
        private List<Address> addresses;
    }
    

    使用补丁:如果您要更新部分资源、资源子集和关系

    USE PUT:如果您要用全新的表示替换资源

    【讨论】:

    • 更新了答案。请检查并告知。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-24
    • 2018-12-10
    • 1970-01-01
    • 2015-09-09
    • 2013-08-21
    • 2018-10-08
    • 2015-04-26
    相关资源
    最近更新 更多