Spring data rest一对多删除子对象

Spring data rest one to many delete child objects

我在 Team 和 Player 之间有一对多的关系,我可以用以下 JSON

创建一个 Team
{
    "id": 1,
    "name": "MyTeam5",
    "players": [
        {
            "name": "player5"
        },
        {
            "name":"player10"
        }
    ]
}

但是,当我尝试通过使用以下 JSON

从列表中删除子对象来删除它时
{
        "id": 1,
        "name": "MyTeam5",
        "players": [
            {
                "id": 2
                "name": "player5"
            }
        ]
    }

我收到一条错误消息

"A collection with cascade=\"all-delete-orphan\" was no longer referenced by the owning entity instance: org.a.c.domain.user.Team.players"

这是我的团队和玩家实体代码 -

@Data
@Entity
public class Team {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    @JsonManagedReference
    @OneToMany(mappedBy="team", cascade= CascadeType.ALL, orphanRemoval=true)
    List<Player> players = new ArrayList<Player>();

}

@Data
@Entity
public class Player {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    @JsonBackReference
    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;
}

我做错了什么?当我用一群球员创建一个新团队时,杰克逊能够完美地映射一对多关系,但是当我更新/删除团队 json 中的球员时,它会失败并出现相同的错误。是否有可能重新创建集合,这就是休眠抛出错误的原因,如果是这样,我应该如何修复它?请帮助

您面临的问题来自players列表的替换。 Hibernate 需要跟踪删除了哪些元素,并在特定列表实现的帮助下执行此操作(据我记得 PersistentList)。

当您或其他人致电 setPlayers 时,问题最有可能出现。用新实例有效地替换列表。

要解决此问题,您有两种可能性:

  • 使用 getPlayers.remove / add
  • 避免调用 setPlayers
  • 或修改 setPlayers 以避免设置新列表,而是清除加载的列表并添加参数列表中的所有元素。

一个简单的例子:

public void setPlayers(List list) {
    if (this.players == null) {
        this.players = list;
    } else {
        this.players.clear();
        this.players.addAll(list);
        // you might need to take care of bidirectional references here
    
}

你可能是对的,集合正在被替换。

我假设有一个 TeamRepository 和一个 PlayerRepository 并且都被导出。这意味着 Team 响应会公开 players link,您可以在其中 post 应该在团队中的玩家的 URI。如果播放器实体不存在,则首先创建它。这就是 Spring Data REST 的工作方式。

另请记住,公开数据库 ID 并不完全是 RESTful。资源的 ID 是它的 URI。

我在使用 spring-boot 时遇到过同样的问题。将 spring-boot-starter-parent 从 1.4.3.RELEASE 更新到 1.4.4.RELEASE 解决了问题:

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.4.RELEASE</version>

在后台,它正在更新一些依赖项,其中之一是 spring-data-rest-webmvc。它从 2.5.6.RELEASE 更新到 2.5.7.RELEASE:

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
<version>2.5.7.RELEASE</version>

这是解决我问题的特定依赖项更新。

不知道是bug还是spring-data-rest的特性。这个用例非常基础。但是由于使用所有这些框架(spring-data-rest、spring-data-jpa)或 spring-boot 默认堆栈都是关于抽象的,所以在我看来它是由 spring-data-rest 以某种方式处理的,因为只要发送的 JSON 是正确的并且 JPA 实体配置是正确的。理想情况下,我不想处理 Hibernate 的特殊性。

你在使用 PATCH 和 PUT 吗?

在 Spring 数据剩余的情况下,调用 PUT will replace your resource completely (and as I understand, create a new, untracked collection), whereas PATCH 只会部分更新您的实体。

在你的情况下,我会说使用 PATCH 是正确的调用,根据我的经验,有时可以解决这个问题。