Hibernate Cascade:在子表中取消引用父PK而不删除子对象

时间:2011-07-15 18:01:37

标签: java hibernate

如果父对象以3个子对象的列表开始,删除子1并调用session.update(parent),我需要什么样的hibernate映射才能从已删除的子表中清除父PK完全删除被删除的孩子?

我还有一个约束,它可以防止任何父项被分配给任何子项,而另一个约束会阻止我意外地级联删除任何子项。

我可以通过简单地调用session.update(parent)来成功级联更新子项,但是我在反向时遇到了麻烦。

public class Parent implements Serializable {
  private static final long serialVersionUID = 1L;
  private Long id;
  private List<Child> children;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  @OneToMany(mappedBy = "parent")
  @org.hibernate.annotations.Cascade( 
        value = {org.hibernate.annotations.CascadeType.SAVE_UPDATE})
  public List<Child> getChildren() {
    return children;
  }

  public void setChildren(List<Child> children){
    this.children = children;
    for(Child child : children) {
      child.setParent(this);
    }
  }

  //-----------------   Would I need something like this?  ---------------
  //----------------- Or does hibernate have a better way? ---------------
  public void setChildren(List<Child> children){

    for(Child child : this.children)
        if (!children.contains(child)) {
          child.setParent(null);
        }
    }
    this.children = children;
    for(Child child : children) {
      child.setParent(this);
    }
  }
  //----------------------------------------------------------------
}

public class Child implements Serializable {
  private static final long serialVersionUID = 1L;
  private Long id;
  private Parent parent;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  @ManyToOne
  public Parent getParent() {
    return parent;
  }

  public void setParent(Parent parent) {
    this.parent = parent;
  }
}

此解决方案类似,但我没有删除Parent,而是我从列表中删除了一个Child:

hibernate cascade - update child to null

2 个答案:

答案 0 :(得分:0)

我认为您必须手动将已删除元素的父级设置为null。休眠中没有任何东西能为你做到这一点。使用Better Beans Binding Project中的Observable Collection可以做得更好。然后,您可以删除您的setter,并立即反映更改。

public class Parent implements Serializable, ObservableListListener {
     private static final long serialVersionUID = 1L;
  private Long id;
  private List<Child> children;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  @OneToMany(mappedBy = "parent")
  @org.hibernate.annotations.Cascade( 
        value = {org.hibernate.annotations.CascadeType.SAVE_UPDATE})
  public List<Child> getChildren() {
    return children;
  }
  void  listElementPropertyChanged(ObservableList list, int index) { // Do Nothing }
  void  listElementReplaced(ObservableList list, int index, java.lang.Object oldElement) {
       listElementAdded(list.get(index));
       listElementRemoved(oldElement);
  }
  void  listElementsAdded(ObservableList list, int index, int length) {
       for(int i = index; i < index + length; i++) {
          ((Child)list.get(i)).setParent(this);
       }
  }
  void  listElementsRemoved(ObservableList list, int index, java.util.List oldElements) {
       for(object element : oldElements) {
          ((Child)list.get(i)).setParent(null);
       }
   }
}

答案 1 :(得分:0)

如果子表中的FK父字段没有非空约束,则可以将parent设置为null并保存子项。

我会写下面的方法:

Boolean removeChild(Child c) {
    Boolean success = getChildren().remove(c);
    if(success) c.setParent(null);
    return success;
 }

我要小心覆盖setChildren方法,因为hibernate需要普通的getter和setter。