修改Spring Data Rest中的@OneToMany实体而不使用其存储库

rot*_*ter 11 java rest spring-data-rest json-patch

在项目中,我使用的类型的对象一个具有一对多的关系(orphanRemoval = TRUE,级联= CascadeType.ALL,取= FetchType.EAGER)至类型的对象.我需要SpringDataRest(SDR )使用单个POST请求来存储完整的完整A对象及其B对象(子对象).我在SDR中尝试了几种组合,唯一对我有用的组合是为对象A创建@RepositoryRestResource并为对象B创建@RepositoryRestResource ,但是将此(B)标记为exported = false(如果我没有创建存储库)在对象B之外,它不起作用 - >只是一个对象将存储在单个POST请求中,而不是它的子类型(@OneToMany关系)类型B ;如果B存储库省略了exported = false,则会出现相同的结果).这是否正确,以及如何实现它的唯一方法(单个POST请求同时存储所有对象)?

我之所以要问,在我之前的例子中,我必须(我想)通过使用A的存储库来控制所有对象"生命周期" .我很好,因为A - > B关系是组合(B不存在于A之外).但是我有严重的问题,即使用其父存储库通过SDR 编辑(也删除)B类型的某个对象(因为对象B没有导出自己的存储库).也许,根据定义,这是不可能的.我试过这些解决方案:

  • "/ A/1/B/2"的PATCH不起作用 - >方法不允许(在标题中是"允许:GET,DELETE") - >所以,PUT也是不可能的
  • 使用json补丁内容类型[{"op":"add","path":"/ B/2",....}] - > JCH Patch也无法使用 - PATCH for"/ A/1" "目标数组中没有这样的索引" - 因为Json Patch在"array"之后使用标量"2"作为其数组的索引.这在Java世界中是不实际的,当关系保存在对象集中时 - 索引根本就没有意义.
  • 我可以导出对象B的存储库(exported = true)以"直接"操作它,但是这样我就会失去将整个对象A及其B对象存储在一个POST请求中的能力,如前所述.

如果可能的话,我想避免发送整个A对象,只需对PUT的B对象进行一次微小的修改.谢谢.

Mat*_*nkt 5

我设法如下更改子实体。作为示例,我使用了以下实体:

@Entity
@Data
@NoArgsConstructor
public class One {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(cascade = ALL)
    private List<Many> manies = new ArrayList<>();

}

@Entity
@Data
@NoArgsConstructor
public class Many {

    public Many(String name) {
        this.name = name;
    }

    @Id
    @GeneratedValue
    private Long id;

    private String name;
}
Run Code Online (Sandbox Code Playgroud)

我只是有一个One暴露库。

(我的示例使用了出色的httpie-CLI HTTP client

使用JSON补丁删除项目

本示例将删除Manies列表中的第二项。您可以使用@OrderColumn来确保可以依赖列表项的顺序。

echo '[{"op":"remove", "path":"/manies/1"}]' | http PATCH :8080/ones/1 Content-Type:application/json-patch+json -v

PATCH /ones/1 HTTP/1.1
Content-Type: application/json-patch+json

[
    {
        "op": "remove", 
        "path": "/manies/1"
    }
]
Run Code Online (Sandbox Code Playgroud)

使用json补丁替换整个列表

此示例将列表替换为值中指定的数组。

echo '[{"op":"add", "path":"/manies", "value":[{"name":"3"}]}]' | http PATCH :8080/ones/1 Content-Type:application/json-patch+json -v

PATCH /ones/1 HTTP/1.1
Accept: application/json
Content-Type: application/json-patch+json

[
    {
        "op": "add", 
        "path": "/manies", 
        "value": [
            {
                "name": "3"
            }
        ]
    }
]
Run Code Online (Sandbox Code Playgroud)

使用json补丁将项目添加到列表

此示例将一个项目添加到列表的末尾。同样在这里,客户端只需要知道更新之前列表的长度即可。因此,这里的顺序并不重要。

echo '[{"op":"add", "path":"/manies/-", "value":{"name":"4"}}]' | http PATCH :8080/ones/1 Content-Type:application/json-patch+json -v

PATCH /ones/1 HTTP/1.1
Accept: application/json
Content-Type: application/json-patch+json

[
    {
        "op": "add", 
        "path": "/manies/-", 
        "value": {
            "name": "4"
        }
    }
]
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。