Spring JPA、Hibernate 仅从其他实体获取 PK 或 ID
Spring JPA, Hibernate fetch PK or Ids only from other entities
我有如下三个实体:
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;
}
盛大Child:
@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;
}
当我调用 parentRepository.findById(id)
时,我会得到一个 parent 及其 children和children的大Child仁。但是,这会导致 2 个问题:
无限递归com.fasterxml.jackson.databind.JsonMappingException:
因为所有实体都包含对彼此的引用。
来自 Hibernate 的不必要查询,因为我的 ParentDto
只包含 List<Long> childrenIds
是否可以使 Hibernate 仅从每个实体的引用中查询 Id 或 PK 而不是获取整个 object ?类似于:
Parent: {
"parentName" : "Parent Name",
"children" : [ {
"id" : 0
}, {
"id" : 1
}, {
"id" : 2
} ]
}
或者:Parent: {"parentName" : "Parent Name", "childrenIds" : [0, 1, 2]}
关于第一个问题 - 为避免无限递归,只需将注释 @JsonIgnoreProperties 添加到每个 'child' 集合,例如:
@JsonIgnoreProperties("parent")
private List<Child> children;
@JsonIgnoreProperties("child")
private List<GrandChild> grandChildren;
所以给定一个 parentId
你想检索 parentName
并且只检索关联的 childIds
-
与其通过 parentRepository
,我更愿意在 childRepository
中添加一个 new method with @Query
。方法和@Query 如下所示:
@Query("select c.parent.id, c.parent.parentName, c.id from Child c where c.parent.id = ?1")
List<Object[]> findChildIdsByParentId(Long parentId);
每个对象 [] 将在索引 0 处包含 parentId,在索引 1 处包含 parentName,在索引 2 处包含 childId。
获得此数据后,您可以将其填充到满足您 json 格式的 DTO(杰克逊稍后序列化)中。
我有如下三个实体:
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;
}
盛大Child:
@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;
}
当我调用 parentRepository.findById(id)
时,我会得到一个 parent 及其 children和children的大Child仁。但是,这会导致 2 个问题:
无限递归
com.fasterxml.jackson.databind.JsonMappingException:
因为所有实体都包含对彼此的引用。来自 Hibernate 的不必要查询,因为我的
ParentDto
只包含List<Long> childrenIds
是否可以使 Hibernate 仅从每个实体的引用中查询 Id 或 PK 而不是获取整个 object ?类似于:
Parent: {
"parentName" : "Parent Name",
"children" : [ {
"id" : 0
}, {
"id" : 1
}, {
"id" : 2
} ]
}
或者:Parent: {"parentName" : "Parent Name", "childrenIds" : [0, 1, 2]}
关于第一个问题 - 为避免无限递归,只需将注释 @JsonIgnoreProperties 添加到每个 'child' 集合,例如:
@JsonIgnoreProperties("parent")
private List<Child> children;
@JsonIgnoreProperties("child")
private List<GrandChild> grandChildren;
所以给定一个 parentId
你想检索 parentName
并且只检索关联的 childIds
-
与其通过 parentRepository
,我更愿意在 childRepository
中添加一个 new method with @Query
。方法和@Query 如下所示:
@Query("select c.parent.id, c.parent.parentName, c.id from Child c where c.parent.id = ?1")
List<Object[]> findChildIdsByParentId(Long parentId);
每个对象 [] 将在索引 0 处包含 parentId,在索引 1 处包含 parentName,在索引 2 处包含 childId。
获得此数据后,您可以将其填充到满足您 json 格式的 DTO(杰克逊稍后序列化)中。