Spring数据休息一对多删除子对象

时间:2015-04-27 16:35:21

标签: json spring hibernate spring-data-jpa spring-data-rest

我在Team和Player之间有一对多的关系,我可以使用以下JSON创建一个团队

{
        "id": 1,
        "name": "MyTeam5",
        "players": [
            {
                "id": 2
                "name": "player5"
            }
        ]
    }

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

将其从列表中删除来删除子对象时
"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;
}

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

    #include <fcntl.h>
    #include <regex.h>
    ...

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

4 个答案:

答案 0 :(得分:4)

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

问题最有可能发生在您身上或setPlayers。使用新实例有效替换列表。

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

  • 使用setPlayers
  • 来避免拨打getPlayers.remove / add
  • 或修改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

}

答案 1 :(得分:0)

您可能是正确的,正在更换该集合。

我假设有一个TeamRepository和一个PlayerRepository,两者都会被导出。这意味着Team响应会公开players链接,您可以在其中发布应该在团队中的玩家的URI。如果玩家实体尚不存在,则先创建它。这就是Spring Data REST的工作方式。

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

答案 2 :(得分:0)

我使用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的特性。

答案 3 :(得分:0)

您使用的是PATCH og PUT吗?

对于Spring Data Rest,调用PUT将完全替换您的资源(据我所知,创建一个新的未跟踪的集合),而PATCH只会部分更新您的实体。 / p>

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