Reputation: 3692
I have an issue with Spring Boot / Spring Data whereby I can only create nested entities in one direction.
I have two entities, Parent and Child, and a Parent has a OnetoMany relationship with the Child entity.
If I create a Child, by doing this:
POST http://localhost:8080/children
{
"name": "Tenzin"
}
and then create a Parent by doing this:
POST http://localhost:8080/parents
{
"name": "Fred and Alma",
"children": [ "http://localhost:8080/children/1" ]
}
it doesn't work.
However, if I create the parent first, and then create a new child by doing this, it does work:
POST http://localhost:8080/children
{
"name": "Jacob",
"parent": [ "http://localhost:8080/parents/1" ]
}
Why is this the case, is this expected behaviour or am I doing something wrong?
Is it because the Parent entity (see below) has cascade=ALL on the children property?
Parent entity:
@Entity
public class Parent {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy="parent", cascade = CascadeType.ALL)
private List<Child> children = new ArrayList<>();
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Child entity:
@Entity
public class Child {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
private Parent parent;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Upvotes: 1
Views: 2048
Reputation: 3692
See Benkuly's reponse above, basically, an association must have an owner, which has to exist for any relationship to exist. See the Hibernate docs:
The association may be bidirectional. In a bidirectional relationship, one of the sides (and only one) has to be the owner: the owner is responsible for the association column(s) update. To declare a side as not responsible for the relationship, the attribute mappedBy is used. mappedBy refers to the property name of the association on the owner side. In our case, this is passport. As you can see, you don't have to (must not) declare the join column since it has already been declared on the owners side.
Upvotes: 0
Reputation: 1194
In you example the child is the owner of the relationchip (it's saved in the child table of database). I think there is the problem. Spring Data Rest loads the child object into the "children" field, but doesn't know that it also should change the "parent" field of the children object. (see also https://stackoverflow.com/a/1796501/7226417).
You can solve this with catching a Spring Data Rest Event (http://docs.spring.io/spring-data/rest/docs/current/reference/html/#events) and manually set the "parent" field.
Upvotes: 2