我有一个Java (使用Spring框架),前端用来创建新的父对象(json),其中包含一个新的子对象列表,如下所示:
parent = {
children: [
{
childName: 'name1'
},
{
childName: 'name2'
}]
}正如您所看到的,那里没有ID,因为我要保存它们,并且数据库应该生成ID。
父实体在后端具有以下代码:
@OneToMany(cascade = {CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "parent")
private Set<Child> children = new HashSet<>();在对父库调用存储库'save‘操作之后,我可以在数据库中找到子元素(所以级联工作了),但是数据库中子列的'parentId’列为null,因此当我得到父元素时,其子列的列表显示为空。
我可以通过在我的服务类中这样做来解决这个问题:
repository.save(parent);
parent.getChildren().forEach((child) -> child.setParent(parent));它起作用是因为(我猜)到那时,父表已经由数据库为它生成了一个ID,因此子表可以将该ID用于其parentId列。它可以工作,但感觉这应该是一个标准的一对多的关系,并且应该由框架以比这更漂亮的方式自动处理。所以我的问题是:我错过了什么?
在级联操作期间保存子实体'parentId‘列时,Hibernate是否可以自动填充它们?
编辑:实际上,这可能是由MapStruct引起的,我使用它将DTO映射到POJO和back。还不确定,但将继续调查(参见相关链接:https://github.com/mapstruct/mapstruct/issues/1068)
发布于 2018-07-19 10:19:51
我想明白了,这不是冬眠的问题,抱歉。
问题是我使用MapStruct来使用更简单的前端对象。这将对象分离为POJO及其各自的DTO对象。DTO对象没有对整个其他对象的引用,它们只是将一些更相关的部分复制到它们中,以使json更简单。
因此,例如,ChildDTO只有
{
name : 'name',
parentId: '1'
}然后,当调用从前端到后端时使用MapStruct,将DTO转换为真正的Java对象,在数据库('ish')中通过id查找父对象,并将其添加到子对象。但是,在默认情况下,它不知道将父引用添加到没有parentId集的子元素中,即使它们是作为父元素(!)的一部分出现的。因此,在Java类中,父引用为null。
至少有两种解决办法:
MapStruct解决方案:
将自定义映射代码添加到MapStruct映射器中,以手动设置作为父元素一部分发送的所有子元素的父引用。请参阅这里
Java解决方案:
在运行MapStruct之后,但在保存到数据库之前,手动添加对所有子级的父引用:
// MapStruct first maps the DTO to a real Parent object, then:
parent.getChildren().forEach((child) -> child.setParent(parent));
parentRepository.save(parent);发布于 2018-07-18 16:49:37
下面是一些关于如何创建实体和添加子实体的基本知识。正如您将看到的那样,您将不必迭代子程序并在其中设置父引用。
public class Parent implements Serializable {
//bi-directional many-to-one association to Children
@OneToMany(mappedBy="Parent")
private List<Children> children;
public List<Children> getChildren() {
return children;
}
public void setChildren(List<Children> children) {
this.children= children;
}
public Children addChildren(Children child) {
getChildren().add(child);
child.setParent(this);
return child;
}
public Children removeChildren(Children child) {
getChildren().remove(child);
child.setParent(null);
return child;
}
}现在创建父对象并调用addChildren来正确设置引用。希望能帮上忙。
发布于 2018-08-24 02:30:14
很好的解决方案--几天来一直在讨论同样的问题,我有一个级联的oneToOne、oneToMany等,用来生成一个相当广泛的xml。我还得在父母身上加上级联。
GrandParent finalGrandParent = grandparent;
grandparent.getParent().getChildren().forEach(child -> child.setParent(finalGrandParent.getParent()));https://stackoverflow.com/questions/51406720
复制相似问题