【发布时间】:2018-03-31 20:39:18
【问题描述】:
我有以下三个实体:
父母:
@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;
}
孩子:
@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;
}
孙子:
@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) 时,我会得到一个父母及其孩子和孩子的grandChildren。但是,这会导致 2 个问题:
无限递归
com.fasterxml.jackson.databind.JsonMappingException:,因为所有实体都包含相互引用。来自 Hibernate 的不必要查询,因为我的
ParentDto仅包含List<Long> childrenIds
有没有办法让 Hibernate 从每个实体的引用中仅查询 Id 或 PK 而不是获取整个对象?类似的东西:
Parent: {
"parentName" : "Parent Name",
"children" : [ {
"id" : 0
}, {
"id" : 1
}, {
"id" : 2
} ]
}
或者:Parent: {"parentName" : "Parent Name", "childrenIds" : [0, 1, 2]}
【问题讨论】:
-
我会得到一个父母和它的孩子和孩子的孙子:不,你不会。 OneToMany 关联是惰性的。 无限递归:否:Hibernate 当然可以处理这个问题,既然您将 DTO 序列化为 JSON,为什么要将实体序列化为 JSON?
-
@JBNizet 我创建了 1 个父母和 3 个孩子,每个孩子有 3 个孙子。当我找回那个父母时,我有 3 个孩子和所有 9 个孙子。我究竟做错了什么 ? [图片链接]:imgur.com/JYypVjc [图片链接]:imgur.com/vC08yPo
-
@JBNizet 关于无限递归:只是有时我将数据记录出来查看,它会引发异常。
-
您只想获取
childIds而不是grandChildrenIds。对吗? -
通过将父级序列化为 JSON,Jackson 在子级集合中导航,然后到孙子级集合,以生成 JSON。这迫使 JPA 初始化惰性集合,从而从数据库中加载所有内容。如果您没有要求将父级序列化为 JSON 的日志记录语句,而是仅将父级转换为 DTO,而不通过孙子导航(因为您不希望它们出现在 DTO 中),JPA 不会初始化 th 孙子集合。
标签: hibernate jpa spring-data-jpa bidirectional multi-level