I have three entities as below:
Parent:
@Setter
@Getter
@Entity
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String parentName;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, targetEntity = Child.class)
private List<Child> children;
}
Child:
@Setter
@Getter
@Entity
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String childName;
@ManyToOne(targetEntity = Parent.class, cascade = CascadeType.MERGE)
@JoinColumn(name = "parent_id")
private Parent parent;
@OneToMany(mappedBy = "child", cascade = CascadeType.ALL)
private List<GrandChild> grandChildren;
}
GrandChild:
@Getter
@Setter
@Entity
public class GrandChild {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(cascade = CascadeType.MERGE, targetEntity = Child.class)
@JoinColumn(name = "child_id")
private Child child;
}
When i call parentRepository.findById(id)
, i would get a parent with its children and children's grandChildren. However, this would cause 2 problems:
Infinite recursion com.fasterxml.jackson.databind.JsonMappingException:
because all entities contain references to each other.
Unnecessary queries from Hibernate since my ParentDto
only contains List<Long> childrenIds
Is there anyway to make Hibernate to query only Id or PK from each entity's references rather then fetch the whole object ? Something like:
Parent: {
"parentName" : "Parent Name",
"children" : [ {
"id" : 0
}, {
"id" : 1
}, {
"id" : 2
} ]
}
Or: Parent: {"parentName" : "Parent Name", "childrenIds" : [0, 1, 2]}
So given a parentId
you want to retrieve the parentName
and only the associated childIds
-
Instead of going via parentRepository
, I would prefer adding an new method with @Query
in the childRepository
. The method and @Query would like below:
@Query("select c.parent.id, c.parent.parentName, c.id from Child c where c.parent.id = ?1")
List<Object[]> findChildIdsByParentId(Long parentId);
Each object [] will contain parentId at index 0, parentName at index 1 and childId at 2.
Once you have this data you can populate this in a DTO (which jackson serializes later) that meets you json format.