首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Hibernate级联一到多没有正确地连接子和父级

Hibernate级联一到多没有正确地连接子和父级
EN

Stack Overflow用户
提问于 2018-07-18 16:17:06
回答 3查看 2.4K关注 0票数 2

我有一个Java (使用Spring框架),前端用来创建新的父对象(json),其中包含一个新的子对象列表,如下所示:

代码语言:javascript
运行
复制
parent = {
    children: [
    {
        childName: 'name1'
    },
    {
        childName: 'name2'
    }]   
}

正如您所看到的,那里没有ID,因为我要保存它们,并且数据库应该生成ID。

父实体在后端具有以下代码:

代码语言:javascript
运行
复制
@OneToMany(cascade = {CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "parent")
private Set<Child> children = new HashSet<>();

在对父库调用存储库'save‘操作之后,我可以在数据库中找到子元素(所以级联工作了),但是数据库中子列的'parentId’列为null,因此当我得到父元素时,其子列的列表显示为空。

我可以通过在我的服务类中这样做来解决这个问题:

代码语言:javascript
运行
复制
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)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-07-19 10:19:51

我想明白了,这不是冬眠的问题,抱歉。

问题是我使用MapStruct来使用更简单的前端对象。这将对象分离为POJO及其各自的DTO对象。DTO对象没有对整个其他对象的引用,它们只是将一些更相关的部分复制到它们中,以使json更简单。

因此,例如,ChildDTO只有

代码语言:javascript
运行
复制
{ 
    name : 'name',
    parentId: '1'
}

然后,当调用从前端到后端时使用MapStruct,将DTO转换为真正的Java对象,在数据库('ish')中通过id查找父对象,并将其添加到子对象。但是,在默认情况下,它不知道将父引用添加到没有parentId集的子元素中,即使它们是作为父元素(!)的一部分出现的。因此,在Java类中,父引用为null。

至少有两种解决办法:

MapStruct解决方案:

将自定义映射代码添加到MapStruct映射器中,以手动设置作为父元素一部分发送的所有子元素的父引用。请参阅这里

Java解决方案:

在运行MapStruct之后,但在保存到数据库之前,手动添加对所有子级的父引用:

代码语言:javascript
运行
复制
// MapStruct first maps the DTO to a real Parent object, then:
parent.getChildren().forEach((child) -> child.setParent(parent));
parentRepository.save(parent);
票数 2
EN

Stack Overflow用户

发布于 2018-07-18 16:49:37

下面是一些关于如何创建实体和添加子实体的基本知识。正如您将看到的那样,您将不必迭代子程序并在其中设置父引用。

代码语言:javascript
运行
复制
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来正确设置引用。希望能帮上忙。

票数 0
EN

Stack Overflow用户

发布于 2018-08-24 02:30:14

很好的解决方案--几天来一直在讨论同样的问题,我有一个级联的oneToOne、oneToMany等,用来生成一个相当广泛的xml。我还得在父母身上加上级联。

代码语言:javascript
运行
复制
GrandParent finalGrandParent = grandparent;
grandparent.getParent().getChildren().forEach(child -> child.setParent(finalGrandParent.getParent()));
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51406720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档