I am using Spring Data REST in my project and I have a problem with relationships when I edit the main entity. This is a simple version of my model:
@MappedSuperclass
public abstract class AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// Getters and setters
}
@Entity
public class Player extends AbstractEntity {
private String category;
private String fnuCode;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(name = "player_contact", joinColumns = @JoinColumn(name = "id_player"), inverseJoinColumns = @JoinColumn(name = "id_contact"))
private List<Contact> contacts;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "id_person")
private Person person;
// Getters and setters
}
@Entity
public class Contact extends AbstractEntity {
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "id_person")
private Person person;
private String relationship;
// Getters and setters
}
@Entity
public class Person extends AbstractEntity {
private String name;
private String lastname;
private String idCard;
// Getters and setters
}
Then, I have my PlayerRepository:
@RepositoryRestResource(path = "players", excerptProjection = PlayerList.class)
@CrossOrigin(origins = "http://localhost:8081")
public interface PlayerRepository extends PagingAndSortingRepository<Player, Long> {
}
PlayerDetail is the projection I use when see and edit a player:
@Projection(name = "playerdetail", types = { Player.class })
public interface PlayerDetail {
@Value("#{target.person.name} #{target.person.lastname}")
String getFullName();
@Value("#{target.person.idCard}")
String getIdCard();
@Value("#{target.category}")
String getCategory();
@Value("#{target.fnuCode}")
String getFnuCode();
List<Contact> getContacts();
}
I don't have any repository for contacts since they are created and modified into the player context.
This is a sample json response I get when I want to edit or see the details of a player (the object is generated from playerdetail projection):
{
"idCard" : "12365478",
"fnuCode" : "1111",
"contacts" : [ {
"person" : {
"name" : "Roberto",
"lastname" : "Perez",
"idCard" : null
},
"relationship" : "Father"
}, {
"person" : {
"name" : "Lucia",
"lastname" : "Perez",
"idCard" : null
},
"relationship" : "Sister"
} ],
"fullName" : "Juancito Perez",
"category" : "U19",
"_links" : {
"self" : {
"href" : "http://localhost:8080/players/171"
},
"jugador" : {
"href" : "http://localhost:8080/players/171{?projection}",
"templated" : true
}
}
}
The problem occurs when I edit the player and remove the first contact of the list, in this case, "Roberto Perez". As a result, in the database the row of Lucia Perez is removed and its data is merged in Roberto Perez row. Before deleting the first contact, I have the following data in DB:
Table: contact
id |id_person |relationship |
175 |176 |Father | --> First contact (Roberto)
178 |179 |Sister | --> Second contact (Lucia)
Table: person
id |id_card |lastname |name
176 |null |Perez |Roberto
179 |null |Perez |Lucia
After deleting first contact (Roberto), I have this:
Table: contact
id |id_person |relationship
175 |176 |Sister
Table: person
id |id_card |lastname |name
176 |null |Perez |Lucia
Note that the ID for the second contact has changed. It should be 178 instead of 175.
EXPECTED RESULT:
Table: contact
id |id_person |relationship
178 |179 |Sister
Table: person
id |id_card |lastname |name
179 |null |Perez |Lucia
The second contact should keep its ID.
I suppose Spring Data REST merges contacts information because there is no univocal way to identify every contact since the id is not exposed in the projection.
I need a way of prevent contacts merging. Is there any other way of managing collections and relationships in Spring Data REST?