简体   繁体   English

将现有子实体映射到新父实体时传递的分离实体保持不变

[英]Detached entity passed to persist when mapping existing child entity to new parent entity

I have two entity as below.我有两个实体如下。

// Parent entity
class Parent {
 @OneToMany(mappedBy = "parent", orphanRemove=true, cascade=CascadeType.ALL)
 Set<Child> children;
}

// Child entity
class Child {
  @ManyToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
  Parent parent;
}

I already have one Parent object which has two Child object and I want to move one Child object from current Parent to new Parent .我已经有一个Parent object,它有两个Child object,我想将一个Child object 从当前的Parent移到新的Parent

@Transactional
public void mapChildToNewParent() {
    // Get existing child and remove it from existing parent
    Parent existingParent = parentRepo.findById(1L);
    Child existingChild = existingParent.getChildren().iterator().next();
    existingParent.remove(existingChild);

    // Create new parent and add existingChild in it
    Parent newParent = new Parent();
    Set<Child> childrens = new HashSet<Child>();
    childrens.add(existingChild);
    newParent.setChildren(childrens)

    // Save modified parent entities
    parentRepo.save(existingParent);
    parentRepo.save(newParent);
}

Now when I do this, save method throws detached entity passed to persist: Child现在,当我这样做时,save 方法会抛出detached entity passed to persist: Child

You're missing a fundamental step in your code: You need to update the association's owning side.您缺少代码中的一个基本步骤:您需要更新关联的拥有方。 Missing that can cause these kinds of exceptions or prevent Hibernate from performing any update on the database.缺少它会导致此类异常或阻止 Hibernate 对数据库执行任何更新。

And you might want to double-check your cascade operations.你可能想仔细检查你的级联操作。 More about that at the end of this post.更多关于这篇文章的结尾。

Disclaimer: I wasn't able to reproduce the error message in my example project.免责声明:我无法在示例项目中重现错误消息。 Instead of the error, Hibernate quietly removed the child record from the database.而不是错误,Hibernate 悄悄地从数据库中删除了子记录。 But that might be a detail that depends on the Hibernate version and/or the surrounding code.但这可能是一个取决于 Hibernate 版本和/或周围代码的细节。

Managing bidirectional associations管理双向关联

Let's start with the most important part: You modeled a bidirectional association.让我们从最重要的部分开始:您为双向关联建模。 When you use it in your business code, you always need to update both sides.当你在你的业务代码中使用它时,你总是需要更新双方。

If you want to dive deeper into association mappings, I recommend studying my best association mapping articles .如果您想更深入地研究关联映射,我建议您阅读我最好的关联映射文章

In your example, the call of the child.setParent(newParent) method is missing:在您的示例中,缺少对child.setParent(newParent)方法的调用:

@Transactional
public void mapChildToNewParent() {
    // Get existing child and remove it from existing parent
    Parent existingParent = parentRepo.findById(1L);
    Child existingChild = existingParent.getChildren().iterator().next();
    existingParent.remove(existingChild);

    // Create new parent and add existingChild in it
    Parent newParent = new Parent();
    Set<Child> childrens = new HashSet<Child>();
    childrens.add(existingChild);
    newParent.setChildren(childrens)

    child.setParent(existingChild);

    // Save modified parent entities
    parentRepo.save(existingParent);
    parentRepo.save(newParent);
}

Using cascading and orphanRemoval使用级联和 orphanRemoval

You're using cascading and orphanRemoval in your mappings.您在映射中使用了级联和orphanRemoval These should only be used for pure parent-child associations in which the child depends on the parent.这些应该只用于孩子依赖于父母的纯亲子关系。 In these cases, having a cascade definition on both ends of the association is uncommon.在这些情况下,在关联的两端都有级联定义是不常见的。 You should double-check if you need the cascade definition on the Child.parent attribute and if it provides the expected results.您应该仔细检查您是否需要Child.parent属性上的级联定义以及它是否提供了预期的结果。

If your parent has many children, cascading a removal operation might cause performance issues .如果您的父母有很多孩子,级联删除操作可能会导致性能问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM