【问题标题】:A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance拥有的实体实例不再引用具有 cascade="all-delete-orphan" 的集合
【发布时间】:2012-03-14 21:31:12
【问题描述】:

在我的应用程序中,休眠操作是这样的。 应用程序使用请求中的新值更新父实体,并删除所有现有(先前插入的)子实体并插入新的子记录。

我正在为此使用休眠 DELETE_ORPHAN,如下所示。

当我这样做时,我得到以下异常:

org.hibernate.HibernateException:一个集合 cascade="all-delete-orphan" 不再被拥有者引用 实体实例:com.childs

我看到了与该问题类似的线程,并尝试在这些线程中应用解决方案。但这没有用

我的父实体

    public class Parent implements Serializable {

            @Column(name = "PARENT_ID")
            @Basic(fetch = FetchType.EAGER)
            @Id
            @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
            @SequenceGenerator(name = "seq", sequenceName = "seq")
            private Integer parentId;  //primary key of parent

            ....... 
            ........

            //mapping to child entity
            @OneToMany(mappedBy = "parent", cascade = { CascadeType.ALL }, fetch =  FetchType.LAZY)
            @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
            private Set<Child> childs;

            ................
            ...............

}

子实体有一个组合键,有一个PK实体如下所示

public class ChildPK implements Serializable {

    /** The Constant serialVersionUID. */
    private static final long serialVersionUID = -447592368963477750L;

    /** . */
    @ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
    @JoinColumns( { @JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID") })
    @Id
    private Parent parent;

    /**. */

    @Column(name = "CHILD_ID")
    @Basic(fetch = FetchType.EAGER)
    @Id
    @GenericGenerator(name="child_seq",    strategy="com.DB2Dialect") 
    @GeneratedValue(generator="child_seq") 
    private Integer childId;

}

child entity goes like this:


public class Child implements Serializable {

    /** The Constant serialVersionUID. */
    private static final long serialVersionUID = 185670997643552301L;

    /** The pol cntct id. */
    @Column(name = "CHILD_ID")
    @Basic(fetch = FetchType.EAGER)
    @Id
    private Integer childId;

    @ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
    @JoinColumns( { @JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID") })
    @Id
    private Parent parent;

}

Java 代码

   ...................
    ..............
    parent.getChild().clear();
    Child child = new Child(); 
    parent.setChild(child);

这里可能有什么问题。
提前谢谢...

【问题讨论】:

标签: hibernate


【解决方案1】:

它改变工作!

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "user_id")
private List<Role> roles;

【讨论】:

    【解决方案2】:

    我遇到了同样的问题并得到解决如下:

    1- 在该元素的所有实体子项的所有 @OneToMany 注释中添加 {CascadeType.ALL}, orphanRemoval=true

    2- 检查这些实体的 hashcode()equalls(),有时它们会出错

    3- 不要使用parent.setChilds(newChilds);,因为引擎会要求缺少对子项的引用,而是使用

    parent.getChilds().clear();
    parent.getChilds().add(Child);
    

    parent.getChilds().addAll(Childs);
    

    经过 4 小时的研究,这些步骤解决了我的问题

    【讨论】:

      【解决方案3】:

      而不是setChilds 使用addAll

      由此,

          parent.getChilds().clear();
          parent.setChilds(newChilds);
      

          parent.getChilds().clear();
          parent.getChilds().addAll(newChilds);
      

      【讨论】:

      • 这些应该添加到哪里?在父实体中还是在子实体中?
      • 在父实体中添加所有子实体
      【解决方案4】:

      它对我有用。

      1. 清除了我的所有子实体。
      2. 我没有将新的子实体设置为我的父对象,而是使用 addAll 方法添加新的子实体。

        parent.getChildren().clear();
        parent.getChildren().addAll(newChildrenList);
        
        @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, 
                   cascade = CascadeType.ALL, orphanRemoval = true)  
        
        public Set<Children> getChildren() {
            return this.children;
        }
        

      【讨论】:

        【解决方案5】:

        您最后的 Java 代码 sn-p 无法编译。我猜它看起来像

        parent.getChilds().clear(); // note: you should name it children rather than childs
        parent.setChilds(someNewSetOfChildren):
        

        不要执行最后一条指令。不要用另一个替换该集合,而是清除该集合并将新子代添加到已清除的集合中:

        parent.clearChildren();
        parent.addChildren(someNewSetOfChildren);
        

        其中方法定义为:

        public void clearChildren() {
            this.children.clear();
        }
        
        public void addChildren(Collection<Child> children) {
            this.children.addAll(children);
        }
        

        setChildren 方法应该被完全删除,或者应该用以下实现替换:

        public void setChildren(Collection<Child> children) {
            this.children.clear();
            this.children.addAll(children);
        }
        

        【讨论】:

        • 对于@JBNizet 我有一个类似的问题,我应用了你的解决方案。实际上,从您指出的 2 个解决方案中,我使用了后者(在 setter 方法中,我清除了子集合 - this.children.clear() - 我添加了新的子 - this.children.addAll(children))。此更改没有解决我的问题。我仍然得到“拥有实体实例不再引用具有 cascade="all-delete-orphan" 的集合”异常。你知道为什么吗?非常感谢!
        • 不,我不知道。您可以提出问题、显示您的代码、完整的堆栈跟踪等。
        • 或许在setChildren中应该添加空检查if (children != null) { this.children.addAll(children);}
        • @lolotron IMO,孩子永远不应该为空。并且忽略新的孩子,如果它比抛出一个 NPE 来发出错误信号更糟糕
        猜你喜欢
        • 2011-08-01
        • 2021-01-09
        • 1970-01-01
        • 2018-03-06
        • 2016-11-26
        • 2023-03-17
        • 2018-10-08
        • 2020-05-28
        相关资源
        最近更新 更多