Hibernate Cascade: De-reference parent PK in child table without removing child object
If a parent object starts off with a list of 3 children objects, removes child 1 and calls session.update(parent), what kind of hibernate mapping would I need in order to clear the parent PK from the removed child table without deleting the removed child completely?
I also have a constraint which prevents any parent from being deleted if any child is assign to it and another constraint that prevents me from accidentally cascade-deleting any child entries.
I can successfully cascade update children by simply calling session.update(parent), but I'm having trouble doing the reverse.
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 : chil开发者_运维问答dren) {
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;
}
}
This solution is similar, but I'm not deleting the Parent, instead I'm removing a Child from the List:
hibernate cascade - update child to null
If you don't have a not-null constraint on the FK parent field in the child table, you can just set parent to null and save the child.
I'd write the following method:
Boolean removeChild(Child c) {
Boolean success = getChildren().remove(c);
if(success) c.setParent(null);
return success;
}
I'd be careful about overwriting the setChildren method, as hibernate needs plain getters and setters.
I think you will have to manually set the parent of the deleted element to null. There is nothing in hibernate that will do this for you. You can do a little better by using an Observable Collection from the Better Beans Binding Project. Then you can remove your setter, and have the changes reflected immediately.
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);
}
}
}
精彩评论