'JPA OneToMany / Parent - Child: can the child hold the parent ID alone?
I am a bit confused about bidirectional parent-child relationships. I have entities like so:
Foo -> Parent -> List of Child
Bar -> Child
if I have on the Parent entity this:
@OneToMany(
fetch = FetchType.EAGER,
mappedBy = "parent",
cascade = CascadeType.ALL,
orphanRemoval = true)
private List<Child> children;
and on the Child entity this:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private Parent parent;
then when attempting JSON serialization of an object including the Bar->Child relationship, where the Child's Parent didn't need to get queried, then the serializer breaks when attempting to make use of Child.parent because the Parent proxy realizes its data hasn't been queried.
I don't actually need Child to have a full Parent member in the JSON. I would like to just have a field on it with "parent_id" as a String (breaking the cycle). But I can't seem to figure out how to get JPA to let me do that, because if I drop the "Parent" field then the mappedBy on the Parent's List[Child] won't work:
mappedBy reference an unknown target entity property
Solution 1:[1]
You can use the @JsonIgnore annotation to prevent the serialization of an attribute, then you can use a @Transient attribute to serialize the parentId. The parent:
@Entity
public class Parent implements Serializable {
@Id
private Integer id;
@OneToMany(
fetch = FetchType.EAGER,
mappedBy = "parent",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Child> children;
public void addChild(Child child) {
if (children == null)
children = new ArrayList<Child>();
child.setParent(this);
child.setParentId(id);
children.add(child);
}
// Getters and setters
}
The child:
@Entity
public class Child {
@Id
private Integer id;
@JsonIgnore
private Parent parent;
@Transient
private Integer parentId;
// Getters and setters
}
Test code:
Parent parent = new Parent();
parent.setId(1);
Child ch1 = new Child();
Child ch2 = new Child();
Child ch3 = new Child();
Child ch4 = new Child();
parent.addChild(ch1);
parent.addChild(ch2);
parent.addChild(ch3);
parent.addChild(ch4);
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(parent));
System.out.println(mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(ch1));
The output:
{
"id" : 1,
"children" : [ {
"parentId" : 1
}, {
"parentId" : 1
}, {
"parentId" : 1
}, {
"parentId" : 1
} ]
}
{
"parentId" : 1
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |