Spring data stores one for many child objects

I have one-one relationship between Team and Player, I can create a team with the following JSON

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

However, when I try to remove the child by removing it from the list with the following JSON

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

I get an error

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

Here is the code for my team and player -

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

What am I doing wrong? Jackson can match one-on-one relationships when I create a new team with a bunch of players, but when I update / delete players from Team json, he fails with the same error. Is it possible that the collection has been recreated, so hibernate throws an error, if so, how can I fix it? Please, help

+6
source share
4 answers

The problem you are facing is with replacing the players list. Hibernate needs to keep track of which items are deleted, and does so using a specific list implementation. "PersistentList" (as far as I remember)

The problem is most likely you or something will be called setPlayers . Effectively replacing the list with a new instance.

To fix the problem, you have two options:

  • avoid calling setPlayers with getPlayers.remove / add
  • or modify setPlayers to avoid setting a new list, but instead clear the loaded list and add all items from the argument list.

Quick example:

 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 } 
+4
source

You may be right that the collection is being replaced.

I assume that there is TeamRepository as well as PlayerRepository , and both are exported. This means that the Team response provides a players link where you can publish the URIs of the players who should be in the team. If the player’s object does not exist yet, you create it first. This is the way Spring Data REST works.

Also keep in mind that mapping database identifiers is not exactly RESTful. The resource identifier is a URI.

0
source

I had the same problem using spring-boot. Updating spring-boot-starter-parent from 1.4.3.RELEASE to 1.4.4.RELEASE solves the problem:

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

Several dependencies are updated under the hood, one of which is spring-data-rest-webmvc. It is updated from 2.5.6.RELEASE to 2.5.7.RELEASE:

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

This is a specific dependency update that solved my problem.

I don't know if this is a bug or a spring -data-rest function. This precedent is indeed the main one. But since using all of these frameworks (spring-data-rest, spring-data-jpa) or spring-boot by default is all abstractions, it seems logical to me that it is somehow handled by spring-data-rest, since the sent JSON is correct and the JPA entity setting is correct. Ideally, I don't want to deal with the features of Hibernate.

0
source

Are you using PATCH og PUT?

In the case of Spring Data Rest, calling PUT will completely replace your resource (and, as I understand it, create a new, non-tracked collection), while PATCH will only partially update your entity.

In your case, I would say that using PATCH is the right call and, in my experience, can sometimes fix this problem.

0
source

Source: https://habr.com/ru/post/986078/


All Articles