当前位置: 首页 > 知识库问答 >
问题:

Hibernate级联一对多不能正确连接子级和父级

马魁
2023-03-14

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

parent = {
    children: [
    {
        childName: 'name1'
    },
    {
        childName: 'name2'
    }]   
}

如您所见,没有ID,因为我即将保存它们,并且数据库应该生成ID。

父实体在后端具有以下html" target="_blank">代码:

@OneToMany(cascade = {CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "parent")
private Set<Child> children = new HashSet<>();

在我调用存储库上的父级保存操作后,我可以在数据库中找到子元素(所以级联工作),但是数据库中的子级的父级列为空,因此当我获取父级时,它的子级列表显示为空。

我可以通过在我的服务课上做这样的事情来解决这个问题:

repository.save(parent);
parent.getChildren().forEach((child) -> child.setParent(parent));

它之所以有效,是因为(我猜)到那时,数据库已经为父表生成了一个ID,所以子表可以将该ID用于其父表列。它有效,但感觉这应该是一个标准的一对多关系,应该由框架以比这更漂亮的方式自动处理。所以我的问题是:我错过了什么?

在级联操作期间保存子实体“parentId”列时,Hibernate是否可以通过某种方式自动填充它们?

编辑:这实际上可能是由我用来将DTO映射到POJO和POJO的MapStruct引起的。尚不确定,但将继续调查(请参阅相关链接:https://github.com/mapstruct/mapstruct/issues/1068)

共有3个答案

漆雕博
2023-03-14

伟大的解决方案-几天来一直处理同一个问题,我有一个级联oneToOne、oneTo多国等,设置以生成相当广泛的xml。我仍然必须将级联添加到父级。

GrandParent finalGrandParent = grandparent;
grandparent.getParent().getChildren().forEach(child -> child.setParent(finalGrandParent.getParent()));
宗政楚
2023-03-14

下面是关于如何创建实体和添加子实体的一些基础知识。正如您将看到的,您不必遍历子实体并在那里设置父引用。

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以正确设置引用。希望有帮助。

皇甫波峻
2023-03-14

我知道了,这不是冬眠问题,真的,对不起。

问题是,我使用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);
 类似资料:
  • 问题内容: 我有以下带注释的Hibernate实体类: 我的意图是在Cat和Kitten之间建立双向的一对多/多对一关系,Kitten是“拥有方”。 我想发生的事情是,当我创建一个新的Cat,然后是一个引用该Cat的新 小猫时,我Cat上的这组小猫应该包含新的Kitten 。但是,在以下测试 中不会发生这种情况 : 即使在重新查询Cat之后,集合仍然为空: 我在这里对Hibernate期望过高吗?

  • 我有两个实体使用Spring和Hibernate

  • 我有一些关于“级联”的问题,在我的项目中,我有类别类,每个类可以是父类或子类。但我在同一个类中定义了哪一个是父母还是孩子。父母和孩子之间存在一对多的关系。这是我的实体类 我的问题是;当我删除子类别时,它的成功并没有问题。如果父类别有子类别,则无法删除父类别。 错误消息; Servlet.service()的servlet[调度Servlet]在上下文中与路径[]抛出异常[请求处理失败;嵌套异常or

  • 问题内容: 我正在使用JPA 2.0并hibernate。我有一个用户类和一个组类,如下所示: 然后,我创建一个用户和组,然后将该用户分配给该组。 我要拥有的是删除组时(当然),该组将被删除,并且该组具有的所有用户-组关系将从USER_GROUP连接表中自动删除,但用户本身不会从USER表。 使用上面的代码,当我删除组时,只有GROUP表中的行将被删除,并且用户在USER_GROUP连接表中仍然具

  • 我有一个非常简单的Spring靴测试 我要从父实体中删除子实体。链接使用的是单向,拥有实体是父实体。我试着给1打电话。,但hibernate最终生成了一个update语句,将parent_name设置为null(而不是delete where parent_name=“father”),这违反了子表中的不可为null约束。 然后我试着打电话给2。,这一次它给出了一个异常。 你如何修复上面的,以使儿

  • 问题内容: 我在我的数据库3个表:,和 学生可以有多个课程,课程可以有多个学生。和之间存在多对多关系。 我为我的项目和课程添加了3个案例。 (a)当我添加用户时,它会保存得很好, (b)当我为学生添加课程时,它会在-预期行为中创建新的行。 (三)当我试图删除学生,则在删除适当的记录和,但它也删除其中不需要的记录。即使课程中没有任何用户,我也希望课程在那里。 下面是我的表和注释类的代码。 这是Hib