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

时间:2016-01-17 20:30:46

标签: java rest spring-data-rest json-patch

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

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

  • PATCH for" / A / 1 / B / 2"不起作用 - >方法不允许(在标题中 是"允许:获取,删除") - >所以,PUT也是不可能的
  • Json Patch也不会工作 - PATCH for" / A / 1"使用json补丁 content-type [{" op":" add"," path":" / B / 2",....}] - > "没有这样的索引 在目标数组" - 因为Json Patch使用标量" 2"在"阵列" 作为其数组的索引。这在Java世界中是不实际的 关系保存在对象集中 - 索引没有意义 完全没有。
  • 我可以导出对象 B 的存储库(exported = true) 直接操纵它"但是这样我就会失去能力 将整个对象 A B 对象一起存储在一个POST中 请求我之前提到的。

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

1 个答案:

答案 0 :(得分: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暴露的存储库。

(我的例子使用优秀的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"
    }
]

使用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 patch

将项目添加到列表中

此示例将项添加到列表的末尾。此外,客户端只需要在更新之前知道列表的长度。所以订单在这里并不重要。

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

希望这有帮助。