修改Spring Data Rest中没有其存储库的@OneToMany实体 [英] Modify @OneToMany entity in Spring Data Rest without its repository

查看:256
本文介绍了修改Spring Data Rest中没有其存储库的@OneToMany实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我使用类型 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请求同时存储所有对象)?

In my project I use object of type A which has OneToMany relation (orphanRemoval = true, cascade = CascadeType.ALL, fetch = FetchType.EAGER) to objects of type B. I need SpringDataRest (SDR) to store complete full A object with its B objects (children) using single one POST request. I tried several combinations in SDR, the only one which worked for me, was to create @RepositoryRestResource for object A and to create @RepositoryRestResource also for object B, but mark this (B) as exported=false (if I did not create repository out of object B at all, it would not work -> just A object would be stored on single POST request, but not its children (@OneToMany relation) of type B; the same outcome occurs if exported=false is omitted for B repository). Is this ok and the only way how to achieve it (single POST request with storing all objects at once)?

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

The reason I'm asking, in my previous example, I have to (I would like to) control all objects "lifecycle" by using A's repository. I am ok with it, because A->B relation is composition (B does not exists outside of A). But I have serious problem of editing (also removing) one certain object of type B by SDR using its parent repository (since object B doest not have its own repository exported). Maybe, this is not possible by definition. I have tried these solutions:


  • / A / 1 / B / 2的PATCH不起作用 - >方法不允许(在标题
    是允许:获取,删除) - >所以,PUT也是不可能的

  • Json Patch也不起作用 - PATCH为/ A / 1使用json补丁
    content-type [{op:add,path:/ B / 2,....}] - >目标数组中没有这样的索引
    - 因为Json Patch在array
    之后使用标量2作为其数组的索引。这在Java世界中是不实际的,当
    关系保存在对象集中时 - 索引根本没有意义

  • 我可以导出存储库(exported =对象 B 对于
    直接操纵它,但是这样我就会失去对
    存储整个对象 A 的能力 B 对象在我之前提到的一个POST
    请求中。

  • PATCH for "/A/1/B/2" does not work -> method not allowed (in headers is "Allow: GET, DELETE") -> so, also PUT is out of question
  • Json Patch would not work either - PATCH for "/A/1" using json patch content-type [{"op": "add", "path": "/B/2", ....}] -> "no such index in target array" - because Json Patch uses scalar "2" after "array" as a index to its array. This is not practical in Java world, when relations are kept in Set of objects - indexing has no meaning at all.
  • I could export repository (exported=true) of object B for manipulating it "directly", but this way I would loose ability to store the whole object A with its B objects at one single POST request as I have mentioned before.

我想要如果可能的话,避免使用其 B 对象的一个​​微小修改来发送整个 A 对象。
谢谢。

I would like to avoid sending the whole A object with one single tiny modification of its B object for PUT, if possible. Thank you.

推荐答案

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

I managed to change the child entity as follows. As a sample I used the following entities:

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

我只有一个公开。

(我的例子使用优秀的 httpie - CLI HTTP客户端

(My examples use the excellent httpie - CLI HTTP client)

使用json补丁删除项目

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

This example will remove the second item in the manies list. You could use @OrderColumn to make sure that you can rely on the order of list items.

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补丁替换整个列表

此示例使用值中指定的数组替换列表。

This sample replaces the list with the array specified in the value.

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补丁将项目添加到列表中

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

This sample adds an item to the end of a list. Also here the client just needs to know the length of the list before the update. So the order does not really matter here.

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

希望这会有所帮助。

这篇关于修改Spring Data Rest中没有其存储库的@OneToMany实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆