11

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

我问的原因是,在我之前的示例中,我必须(我想)通过使用A的存储库来控制所有对象的“生命周期”。我可以接受,因为A -> B关系是组合(B在A之外不存在)。但是我有一个严重的问题,即通过 SDR 使用其父存储库编辑(也删除)一个特定类型的B对象(因为对象B没有导出自己的存储库)。也许,这在定义上是不可能的。我尝试了这些解决方案:

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

如果可能的话,我想避免发送整个A对象并对其B对象进行一个微小的修改以进行 PUT。谢谢你。

4

1 回答 1

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;
}

我只有一个One暴露的存储库。

(我的例子使用了优秀的ht​​tpie - CLI HTTP 客户端

使用 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"
    }
]

使用 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"
            }
        ]
    }
]

使用 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"
        }
    }
]

希望这可以帮助。

于 2016-01-18T21:18:04.543 回答